BD1ファイル解析情報
※データの無断転載は固くお断りします。
ファイルフォーマット概要
.bd1ファイルは、XOPSのマップデータを構成するファイルです。
X operations TOOLS ブロックエディタによれば、BD1の正式名称は"Block Data Version 1"です。
基本的には、「ブロック」と呼ばれる6面体と、そのテクスチャ情報が記録されています。
ファイルフォーマット詳細
ファイル構造
ファイル構造は以下の通りです。
ブロック数によってファイル全体のサイズは可変しますが、各要素の順序とデータ長は固定です。データの並び順はリトルエンディアンです。
| [310Byte] テクスチャパス(31Byte×10枚) |
| [2Byte] ブロック数 |
| [316Byte×ブロック数] 個々のブロックデータ ・96Byte:頂点座標(xyz×8頂点) ・192Byte:テクスチャーUV指定(UV×6面) ・24Byte:テクスチャ番号(6面) ・4Byte:データ有効化フラグ |
テクスチャパス
マップで使用するテクスチャのファイルパスです。bd1ファイルからの相対パスで指定します。
一般的なASCIIで表現され、00(NULL)で終了とみなされます。テクスチャ1枚で31Byte未満の場合は、31Byteまで00(NULL)で埋めます。
ブロック数
マップのブロック数を表します。
本家XOPSの場合ブロック数は最大160個(0xA0)のため、2バイト目は常に0x00になります。
ブロックデータ
ブロックデータの実データを表します。前述のブロック数分、本ブロックデータを定義します。
●頂点座標
ブロック8頂点分の頂点座標を定義します。float型(4Byte)にて「最初にX軸 8座標分、次にY軸 8座標分、最後にZ軸 8座標分」で、計96Byteです。
(x,y,z x,y,z x,y,z ... ではなく、x,x,x,x... y,y,y,y... z,z,z,z... で格納されています。)
なお座標軸は左手系座標で、X-Z平面が水平 Y軸が高さです。
8頂点の格納順序は以下の通りです。

▲ブロックの頂点格納順序
上4点(0–3)+下4点(4–7)のデータ順であり、座標の位置関係は以下の通りとなります。
※ブロック全体が回転している場合、その限りではありません。
・0:x-, y+, z-
・1:x+, y+, z-
・2:x+, y+, z+
・3:x-, y+, z+
・4:x-, y-, z-
・5:x+, y-, z-
・6:x+, y-, z+
・7:x-, y-, z+
●テクスチャーUV指定
テクスチャーのUV座標を6面分指定します。float型(4Byte)を用いて、1面の4隅のU座標を4個×6面、次にV座標を4個×6面、合計192Byteになります。
前述の頂点座標を元に、以下の頂点順序・構成で面を生成します。
1、[1,0,3,2]
2、[6,7,4,5]
3、[5,4,0,1]
4、[6,5,1,2]
5、[7,6,2,3]
6、[4,7,3,0]
●テクスチャ番号
テクスチャ番号をint型の4Byteで6面分指定します。ただしデータの有効範囲は00~09のため、2~4バイト目は常に0x00になります。
●データ有効化フラグ
本ブロックデータ(1個分)のデータ有効化フラグを表します。int型(4Byte)で表現され、ゲームとエディタで挙動が異なります。
本家エディタ:0の場合はエディタ上で表示されず、1以上で表示されます。
ゲーム本体:データ有効化フラグは無意味です。
【参考】JSONによるフォーマット記述メタデータ
{
"format": "BD1",
"long_name": "Block Data Version 1",
"version": 1,
"endianness": "LE",
"coordinate_system": {
"handedness": "left",
"axes": "X-Z horizontal, Y up"
},
"file_structure": {
"header": {
"size": 310,
"texture_paths": {
"count": 10,
"entry_size": 31,
"encoding": "ASCII-NULL",
"path_relative": true
}
},
"block_count": {
"offset": 310,
"size": 2,
"type": "uint16_le",
"note": "Maximum 160 blocks"
},
"blocks": {
"count_ref": "block_count",
"record_size": 316,
"layout": ["vertices", "uv", "texture_index", "enable_flag"]
}
},
"block_layout": {
"vertices": {
"size": 96,
"type": "float32_le",
"vertex_count": 8,
"vertex_order": "X8Y8Z8"
},
"uv": {
"size": 192,
"type": "float32_le",
"order": "U4×6faces then V4×6faces",
"per_face_corners": 4,
"faces": 6
},
"texture_index": {
"size": 24,
"type": "int32_le",
"faces": 6,
"valid_range": [0, 9]
},
"enable_flag": {
"size": 4,
"type": "int32_le",
"usage": "reserved"
}
},
"faces": {
"build_order": [
[1, 0, 3, 2],
[6, 7, 4, 5],
[5, 4, 0, 1],
[6, 5, 1, 2],
[7, 6, 2, 3],
[4, 7, 3, 0]
],
"labels": {
"f0": { "name": "top", "axis": "Y+" },
"f1": { "name": "bottom", "axis": "Y-" },
"f2": { "name": "front", "axis": "Z-" },
"f3": { "name": "right", "axis": "X+" },
"f4": { "name": "back", "axis": "Z+" },
"f5": { "name": "left", "axis": "X-" }
}
}
}
|

