トップ > 開発・技術資料 > ファイル解析情報 > BD1ファイル解析情報(このページ)

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-" }
    }
  }
}