3Dモデル編その②独自形式を作ろう!
皆さんこんにちは。
フルスクラッチでゲームエンジンを作ろう!第七回です。
今回はモデルデータを司る独自フォーマットとマテリアルデータを司る独自フォーマットの仕様を決めようと思います。
モデルのフォーマット名はButi 3DModel Dataの略でB3M、マテリアルはButi Material Dataの略でBMAとします。
データ構造は各所で読みやすいと評判のPMXファイル(MMDのモデルデータ)をめちゃくちゃ参考にします。
PMXエディターについてきているPMX仕様書を見ながら…
B3Mのデータ構造は
-先頭-
ヘッダ
-<マジックナンバー>
Buti3DModelData(15バイト)
バージョン(float)
-<文字列エンコード方式>
文字列エンコード方式(char)
-<制作者>
制作者の名前(int[文字数]+stringもしくはwstring)
制作者の名前英(int[文字数]+stringもしくはwstring)
-<モデル名・コメント>
モデル名(int[文字数]+stringもしくはwstring)
モデル名英(int[文字数]+stringもしくはwstring)
コメント(int[文字数]+stringもしくはwstring)
コメント英(int[文字数]+stringもしくはwstring)
-<各インデックスのデータサイズ>
頂点インデックスのバイト数(char)
マテリアルインデックスのバイト数(char)
ボーンインデックスのバイト数(char)
モーフインデックスのバイト数(char)
-
モデル情報
-<頂点>
頂点の構造(char列挙型)
追加UV数(char)
頂点数(unsigned charもしくはunsigned shortもしくはunsigned int)
頂点(上の構造によってどれだけ情報が詰め込まれているかが変わる){
頂点構造(char)
頂点座標(Vector3)
UV座標(Vector2)
追加UV(Vector4)
追加UV(Vector4)
追加UV(Vector4)
追加UV(Vector4)
法線(Vector3)
ボーン番号(charもしくはshortもしくはint)
ボーン番号(charもしくはshortもしくはint)
ボーン番号(charもしくはshortもしくはint)
ボーン番号(charもしくはshortもしくはint)
ボーンのウェイト(float)
ボーンのウェイト(float)
ボーンのウェイト(float)
ボーンのウェイト(float)
SDEF-C値(Vector3)
SDEF-R0値(Vector3)
SDEF-R1値(Vector3)
} * 頂点数
-<インデックス>
面数(int)
面{
参照頂点Index(unsigned charもしくはunsigned shortもしくはunsigned intの配列)*3
}* 面数
-<マテリアル>
マテリアル数(unsigned charもしくはunsigned shortもしくはunsigned int)
{
マテリアル名 (int[文字数]+stringもしくはwstring)
マテリアルに対応する頂点数(int)
}* マテリアル数
-<ボーン>
ボーン数(charもしくはshortもしくはint)
ボーン{
ボーン名(int[文字数]+stringもしくはwstring)
親ボーンの番号(charもしくはshortもしくはint)
変形階層(int)
ボーン座標(Vector3)
ボーンのフラグ(2バイトでどんなボーンなのかの情報。これによってどれだけ情報が詰め込まれているかが変わる)
ボーンのフラグから接続先、回転可能、移動可能、表示、操作可、IK、ローカル付与、回転付与、
移動付与、軸固定、ローカル軸、物理後変形、外部親変形等の情報を取り出し、以下の情報のうちどれが含まれるか判断します。
接続先座標(Vector3)
もしくは
接続先ボーンのインデックス(charもしくはshortもしくはint)
回転、移動付与する場合
付与先のボーンのインデックス(charもしくはshortもしくはint)
付与率(float)
軸固定する場合
軸のベクトル(Vector3)
ローカル軸がある場合
X軸のベクトル(Vector3)
Z軸のベクトル(Vector3)
外部親変形がある場合
key(unsigned int)
IKが有効な場合
IKのターゲットのボーンインデックス(charもしくはshortもしくはint)
IKのループ回数(unsigned int)
IKの一回当たりの変化制限角(float)
IKのリンク数(unsigned int)
IKリンク{
ボーンのインデックス(int)
角度制限のありなし(1バイト)
角度制限がある場合
下限(Vector3)
上限(Vector3)
}*IKのリンク数
}* ボーン数
-<モーフ>
モーフ数(charもしくはshortもしくはint)
{
モーフ名(stringもしくはwstring)
モーフ名英(stringもしくはwstring)
カテゴリ(char)
モーフの種類(chara型 これを基に、どんな情報が含まれているかを判断、以下の読み込みをする)
モーフのオフセット値(int)
{
頂点モーフの場合
頂点のインデックス(unsigned charもしくはunsigned shortもしくはunsigned int)
頂点のオフセット量(Vector3)
UVモーフの場合
頂点のインデックス(unsigned charもしくはunsigned shortもしくはunsigned int)
UVのオフセット量(Vector4)
マテリアルモーフの場合
マテリアルのインデックス(charもしくはshortもしくはint)
演算形式(char)
Diffuse(Vector4)
Specular(Vector4)
Ambient(Vector4)
テクスチャ係数(Vector4)
スフィアテクスチャ係数(Vector4)
ボーンモーフの場合
ボーンのインデックス(charもしくはshortもしくはint)
グループモーフ
モーフのインデックス(charもしくはshortもしくはint)
モーフ率(float)
フリップモーフ
モーフのインデックス(charもしくはshortもしくはint)
モーフ率(float)
}*モーフのオフセット値
}*モーフ数
-
-終了-
ひとまずこんな感じにします。
続いてBMAは
-先頭-
ヘッダ
-<マジックナンバー>
ButiMaterialData(15バイト)
バージョン(float)
-<文字列エンコード方式>
文字列エンコード方式(char)
-<マテリアル名>
マテリアル名(int[文字数]+stringもしくはwstring)
マテリアル名英(int[文字数]+stringもしくはwstring)
マテリアル情報
-<テクスチャ>
テクスチャ数(char)
{
テクスチャ名(int[文字数]+stringもしくはwstring)
}*テクスチャ数
-<マテリアル>
Diffuse(float4)
Specular(float4)
Ambient(float4)
Emissive(float4)
描画フラグ(裏面カリング、地面影、セルフシャドウマップへの描画、セルフシャドウの描画、エッジ描画)(1バイト)
スフィアモード(char)
コメント(int[文字数]+stringもしくはwstring)
-
-終了-
それでは、実際にこれらの要素を読み込んで描画します。
これまでなかったボーンの概念などを追加した描画データを作成し…
この16進数の羅列から
を生成して描画することができるようになりました。
次回はFBX、PMXデータを今回作成したフォーマットに変換したいと思います。
最後まで読んで頂きありがとうございました。それでは。
この記事が気に入ったらサポートをしてみませんか?