見出し画像

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)
-
-終了-

それでは、実際にこれらの要素を読み込んで描画します。

これまでなかったボーンの概念などを追加した描画データを作成し…

画像1

この16進数の羅列から

を生成して描画することができるようになりました。

次回はFBX、PMXデータを今回作成したフォーマットに変換したいと思います。

最後まで読んで頂きありがとうございました。それでは。

この記事が気に入ったらサポートをしてみませんか?