08、プロジェクトファイル入出力




プロジェクトファイルの入出力機能が付きました。
FileメニューのOpen, Saveで実行します。

プロジェクトファイルの拡張子は*.rdbです。
モーションファイルの拡張子は*.qubです。

両方ともメモ帳で編集できるXML形式です。
ファイルはANSI形式(Shift-JIS)でないといけません。


プロジェクトファイルを保存すると
mqo, テクスチャ、モーションファイル全てがプロジェクトフォルダ以下に作成されます。


ファイル名に日本語は使えますが、内部でUnicodeとマルチバイトを変換する場所があるので
(VSのプロジェクトはUnicodeです。)
ファイル名などにUnicodeでしか表示できない文字を使うとバグります。

テクスチャはmqoと同じフォルダにないとうまく保存できません。
RokDeBone2でmqoを開いている途中に、そのmqoを移動したり名前を変えたりすると
うまく保存できません。

ソースは下のページからダウンロードしてください。
OpenRDBダウンロードページ




08−01、プロジェクトファイルフォーマット

プロジェクトファイルはXMLファイルです。
OpenRDBで保存した後は、メモ帳で編集可能です。
ただしANSI形式(Shift-JIS)で保存しないと読み込みエラーになるので注意してください。

サンプルとして同梱しているプロジェクトファイルを貼り付けます。

<?xml version="1.0" encoding="Shift_JIS"?>
<RDB>
<FileInfo>
<kind>OpenRDBProjectFile</kind>
<version>1001</version>
<type>0</type>
</FileInfo>
<ProjectInfo>
<CharaNum>2</CharaNum>
</ProjectInfo>
<Chara>
<ModelFolder>ラグナ10_0</ModelFolder>
<ModelFile>ラグナ10.mqo</ModelFile>
<ModelMult>1.000000</ModelMult>
<MotionNum>1</MotionNum>
<Motion>
<MotionFile>rgnmot1_0.qub</MotionFile>
<MotionName>rgnmot1</MotionName>
</Motion>
</Chara>
<Chara>
<ModelFolder>猿02_2_1</ModelFolder>
<ModelFile>猿02_2.mqo</ModelFile>
<ModelMult>1.000000</ModelMult>
<MotionNum>1</MotionNum>
<Motion>
<MotionFile>sarumot1_0.qub</MotionFile>
<MotionName>sarumot1</MotionName>
</Motion>
</Chara>
</RDB>

(上記では<>を全角にしていますが実際には半角です。全角スペースも実際には半角です。)

FileInfoはこのファイルがOpenRDBのプロジェクトファイルであることを識別するためのものです。
ProjectInfoには記述しているキャラクターの数を保存します。

キャラクターごとにCharaチャプターを作り、その中に形状とモーションについての記述をします。
ModelFolderというのは1つのキャラクターについての形状とモーションのファイルを格納するフォルダの名前です。
*.rdbファイルのあるフォルダの中のModelFolderの中に形状ファイルを保存します。

MotionNumで記した数だけMotionチャプターを記述します。
Motionチャプターはモーションの名前とファイル名から成ります。


08−02、モーションファイルフォーマット

モーションファイルの一例を貼り付けます。
モーションファイルの拡張子は*.qubです。

<?xml version="1.0" encoding="Shift_JIS"?>
<QUB>
<FileInfo>
<kind>OpenRDBMotionFile</kind>
<version>1001</version>
<type>0</type>
</FileInfo>
<MOTIONINFO>
<Name>rgnmot1</Name>
<FrameLeng>32.000000</FrameLeng>
<Loop>1</Loop>
<BoneNum>23</BoneNum>
</MOTIONINFO>
<Bone>
<Name>ModelRootBone</Name>
<MPNum>4</MPNum>
<MotionPoint>
<Frame>0.0000000</Frame>
<Q>0.000000, 0.000000, 0.000000, 1.000000</Q>
<Eul>0.000000, 0.000000, 0.000000</Eul>
<Tra>0.000000, 100.000000, 0.000000</Tra>
</MotionPoint>
<MotionPoint>
<Frame>10.0000000</Frame>
<Q>0.000000, 0.000000, 0.000000, 1.000000</Q>
<Eul>0.000000, 0.000000, 0.000000</Eul>
<Tra>0.000000, 110.000000, 0.000000</Tra>
</MotionPoint>
<MotionPoint>
<Frame>20.0000000</Frame>
<Q>0.000000, 0.000000, 0.000000, 1.000000</Q>
<Eul>0.000000, 0.000000, 0.000000</Eul>
<Tra>0.000000, 90.000000, 0.000000</Tra>
</MotionPoint>
<MotionPoint>
<Frame>31.0000000</Frame>
<Q>0.000000, 0.000000, 0.000000, 1.000000</Q>
<Eul>0.000000, 0.000000, 0.000000</Eul>
<Tra>0.000000, 120.000000, 0.000000</Tra>
</MotionPoint>
</Bone>
<Bone>
<Name>TOP_胸</Name>
<MPNum>1</MPNum>
<MotionPoint>
<Frame>0.0000000</Frame>
<Q>0.000000, 0.000000, 0.000000, 1.000000</Q>
<Eul>0.000000, 0.000000, 0.000000</Eul>
<Tra>0.000000, 0.000000, 0.000000</Tra>
</MotionPoint>
</Bone>

...省略...

</QUB>

(上記では<>を全角にしていますが実際には半角です。全角スペースも実際には半角です。)


*qubファイル1つに1つのモーションを記述します。
Boneの個数分Boneチャプターがあります。
そしてその中にMPNum個分のMotionPointのチャプターが記述されます。

Qはクォータニオン、Eulはオイラー角(degree)、Traは移動成分です。

08−03、プロジェクトファイル読み込み

*.rdbファイルはCRdbFileで、*.qubファイルはCQubFileで読み書きします。
両方のクラスともCXMLIOというXMLの読み書きの基本機能を定義した基本クラスから派生しています。

書き込みは説明するまでもないでしょう。

読み込みのポイントだけ説明します。
読み込みの一部を見てください。

int characnt;
for( characnt = 0; characnt < charanum; characnt++ ){
XMLIOBUF charabuf;
ZeroMemory( &charabuf, sizeof( XMLIOBUF ) );
CallF( SetXmlIOBuf( &m_xmliobuf, "<Chara>", "</Chara>", &charabuf ), return 1 );
CallF( ReadChara( &charabuf ), return 1 );
}


上のコードはキャラクターの数分ReadCharaでキャラクター情報を読み込む呼び出し部分です。

SetXmlIOBuf( &m_xmliobuf, "<Chara>", "</Chara>", &charabuf );

の部分が何をしているかというと
<Chara>で始まり、</Chara>で終わる部分のバッファをm_xmliobufに記録しています。
チャプターの始まりと終わりまでの長さを記録するのです。

そしてその記録した範囲のバッファの中でReadCharaというキャラクターの読み込み処理を行います。
SetXmlIOBufは記録した後、バッファの位置をその分進めるので
同じ目印でSetXmlIOBufを呼び出すと2個目、3個目のCharaチャプターを見つけることが出来ます。

このようにチャプターの目印から該当するバッファの情報を記録し、
そのバッファの中で読み込み処理を行うという処理を繰り返して読み込みます。

SetXmlIOBufのコードを載せます。

int CXMLIO::SetXmlIOBuf( XMLIOBUF* srcbuf, char* startpat, char*
      endpat, XMLIOBUF* dstbuf )
{
char* startptr = 0;
char* endptr = 0;
startptr = strstr( srcbuf->buf + srcbuf->pos, startpat );
endptr = strstr( srcbuf->buf + srcbuf->pos, endpat );

int spatlen = (int)strlen( startpat );
startptr += spatlen;

if( !startptr || !endptr ){
_ASSERT( 0 );
return 1;
}

int epatlen;
epatlen = (int)strlen( endpat );

int chkendpos;
chkendpos = (int)( endptr + epatlen - srcbuf->buf );
if( (chkendpos >= srcbuf->bufleng) || (endptr < startptr) ){
_ASSERT( 0 );
return 1;
}

srcbuf->pos = chkendpos;

dstbuf->buf = startptr;
dstbuf->bufleng = (int)( endptr - startptr );
dstbuf->pos = 0;
dstbuf->isend = 0;

return 0;
}


このように範囲を狭めていって読み込む方式です。
最終的には絞り込まれたバッファをatof, atoiで変換して読み込みます。

オープンソースのトップに戻る

トップページに戻る