連載
» 2010年03月31日 00時00分 公開

“BREW”アプリケーション開発入門(8):MascotCapsuleによる3Dグラフィックスプログラミング (3/3)

[末永貴一(エイチアイ),@IT MONOist]
前のページへ 1|2|3       

eruptionのデータロード

 以上で開発環境の準備ができましたので、実際にプログラミングを行っていきたいところですが、その前に、プログラム中で準備することがありますので、そちらの解説を先に行います。

 前回のOpenGL ESプログラミングでは、立方体の頂点データをプログラムの中に入れていましたが、eruptionでは頂点データをはじめとする3Dデータやアニメーションデータを別途「モデルデータ」「アクションデータ」として作成し、それをロードして利用するためデータ入出力の実装が必要になります。単純にデータの入出力を扱うだけであればBREWの入出力用のAPIを利用すればよいだけなのですが、eruptionの場合、組み込みミドルウェア特有の実装を行う部分があります。具体的には、BREW以外のさまざまなプラットフォームに対応できるように、ミドルウェアから環境依存が多い入出力部分を切り出し、各アプリケーション側で環境ごとの入出力実装を行う仕様になっています。

eruptionのデータ入出力 図11 eruptionのデータ入出力

 データの入出力は、erutpionの中で「IIStream」というインターフェイスが定義されているだけで、このインターフェイスの実装は、アプリケーション開発側が行うようになっています。つまり、オブジェクト指向のポリモフィズム(多態性)が実現されており、eruption側から見るとIIStreamにアクセスすれば、入出力の実装を気にする必要がなくなり、環境依存をなくせるというメリットがあります。この実装に関してはリファレンスとして、「LMemIstream.c」と「LMemIstream.h」が提供されていますので、今回はこちらを利用して入出力実装を実現します(以下、URL参照)。

「LMemIstream.c」と「LMemIstream.h」のダウンロード:
>>「LMemIstream.c」のダウンロード
>>「LMemIstream.h」のダウンロード

 以上のファイルをダウンロードしたら、プロジェクトの「.c」ファイルと同じ場所に置き、プロジェクトにLMemIstream.cとLMemIstream.hを追加します。このファイルに対する修正は特に行う必要はありません。

「LMemIstream.c」と「LMemIstream.h」の配置 図12 「LMemIstream.c」と「LMemIstream.h」の配置

 LMemIstreamの中を確認してみると、IIStreamのインターフェイスは「仮想関数テーブル(Vテーブル)」によって実現されていることが分かります。

typedef struct tagMemIstream{
        const IIstreamVtbl* vtbl;
        const hi_byte* pointer;
        const hi_byte* end_ptr;
        hi_uint32 bufleft;
        hi_bool eof;
        IIstreamVtbl vftbl;
} LMemIstream; 
LMemIstream.h(抜粋)

Void LMemIstream_initialize (LMemIstream *This, const hi_byte *address, hi_uint32 size){
        This->vftbl.readSint8   = _readSint8;
        This->vftbl.readSint16  = _readSint16;
        This->vftbl.readSint32  = _readSint32;
        This->vftbl.readBytes   = _readBytes;
        This->vftbl.skipBytes   = _skipBytes;
        This->vftbl.fail        = _fail;
        This->vftbl.readFloat   = _readFloat;
        This->vftbl.readString  = _readString;
        This->vtbl = &This->vftbl;
        This->pointer = address;
        This->end_ptr = address + size;
        This->bufleft = size;
        This->eof     = HI_FALSE;
} 
LMemIstream.c(抜粋)

 以上を確認すると、LMemIstream構造体にはIIStreamのVテーブルが含まれており、LMemIstream_initialize()の中で、入力の実装関数がセットされていることが分かります。つまり、IIStreamインターフェイスの実装とは、作成した各ビット列のデータ読み込み関数をVテーブルに登録することを意味しています。

 それでは、アプリケーション側のeruptionデータの読み込み部分の内容を確認してみましょう。

boolean dataLoad(eruption1* pMe, char *file_name){
   FileInfo     info;        // ファイル情報
   IFileMgr    *p_file_mng;  // Fileマネージャ格納
   IFile        *p_file;     // ファイルポインタ
   LMemIstream  mis;         // LMemIstreamのインスタンス(eruption用)
   hi_byte *FileLoadAddress; // ファイル読み込みアドレス(eruption用)
   hi_uint32   load_size;    // ファイルサイズ(eruption用)
   hi_sint32    obj_count;   // ロードオブジェクトのカウンタ(eruption用)
   hi_exception exception;   // 例外格納(eruption用)
 
   // BREWファイル入出力
   ISHELL_CreateInstance(pMe->a.m_pIShell, AEECLSID_FILEMGR, (void**)&p_file_mng );
   p_file = NULL;
   p_file = IFILEMGR_OpenFile(p_file_mng, file_name, _OFM_READ);  // ファイルオープン
   if (p_file == NULL){
           return FALSE;
   }
   if (IFILE_GetInfo(p_file, &info) != SUCCESS){  // ファイル情報の取得
           return FALSE;
   }
   FileLoadAddress = (hi_byte *)MALLOC(sizeof(hi_byte) * info.dwSize);
   // データ読み込み
   load_size = IFILE_Read(p_file, FileLoadAddress, (sizeof (hi_byte) * info.dwSize));
   IFILE_Release(p_file);
   IFILEMGR_Release(p_file_mng);
   // ファイルサイズとロードサイズの整合性チェック
   if (load_size != (sizeof(hi_byte) * info.dwSize)){
           return FALSE;
   }
   // eruption用データ入力
   LMemIstream_initialize(&mis, FileLoadAddress, load_size);
   pMe->Obj3d = mceLoader_load(LMemIstream_getIIstream(&mis), &obj_count,0, &exception);
   // eruption用データ入力チェック
   if (pMe->Obj3d == NULL){
           FREE(FileLoadAddress);
           return FALSE;
   }
   FREE(FileLoadAddress);
   return TRUE;
} 
eruptionデータの読み込み部分の確認

 併せて、ヘッダのインクルードと関数宣言も行います。

#include "eruption_a31.h"
#include "LMemIstream.h"        //インプットストリームの実装
#include "convert.h"            //BREW特有の接頭辞などを省略できるようにする

 上記の「eruption_a31.h」と「convert.h」は、eruption用のヘッダファイルです。convert.hは、OpeGL ESのときにもあったBREW特有のプリフィックスを省略できるようにするためのヘッダファイルです。以降の解説では、これを使うことを前提とします。

boolean dataLoad(eruption1* pMe, char *file_name); 

 前半部分は、BREWのファイル入出力に関する処理です。変数に「hi_」と付いているものがありますが、これはeruption用に用意された独自の型になります。

 ポイントは、後半部分のファイルからロードしたデータをeruptionに渡す部分です。ここではリファレンス実装であるLMemIStreamを利用していますが、LMemIstream_initialize()で行っているのが前述したインターフェイスの実装処理です。ここで、実際に各実装関数がVテーブルに登録されます。第1引数で指定しているLMemIStreamの構造体には、erutpionの入出力オブジェクトであるIIStreamが含まれており、結果としてLMemIstream_initialize()の中で、eruption側の入力と実装側の入力が連結されることになります。そして、LMemIstream_getIIstream()で、LMemIStreamがIIStreamにキャストされ、mceLoader_load()によって3Dデータであるモデルデータがロードされます。

ファイルからロードしたデータをMemIStream経由でeruptionに渡しているイメージ 図13 ファイルからロードしたデータをMemIStream経由でeruptionに渡しているイメージ


 今回は、環境構築の話に終始しましたが、以上でeruptionによる3D描画が可能な状態になりました。eruptionプログラミングにおいて、今回の内容は共通の設定になりますので、以後のプログラムではこの環境を前提に解説を進めます。さて、次回は実際に、eruptionでの3D描画を行いたいと思います。お楽しみに! (次回に続く)

前のページへ 1|2|3       

Copyright © ITmedia, Inc. All Rights Reserved.