Skip to main content

COLBIN

Collision geometry: floor triangles, wall boxes, and a uniform grid over the walls. Produced by tools/blender_colbin.py from a COL collection, consumed by ColbinManager::LoadColbin.

Every multi-byte field is little-endian.

Fixed-point conventions​

Two conventions, and which one applies depends on the field, not on the struct it lives in.

DataConvention
Positions: grid origin, cell size, floor vertices, OBB centre, OBB half extentsx128 integer (128 units per engine metre)
Directions: floor normals, OBB axesFP12 (x4096)

Both end up in fields whose C++ type is nominally 12-bit fixed point, so the type does not tell you which convention a field uses. The table below does.

FieldTypeBytesNotes
magicchar[6]6COLBIN, no terminator. Mismatch aborts the load.
versionuint8_t1Currently 2.
floorTriCountuint32_t4
wallOBBCountuint32_t4

Grid header​

FieldTypeBytesConvention
originXint32_t4x128
originZint32_t4x128
cellSizeuint32_t4x128. Default is 256, i.e. two Blender units.
gridWidthuint16_t2cell count along X
gridHeightuint16_t2cell count along Z

Grid cells​

gridWidth * gridHeight cells follow, in X-major order: X is the outer loop and Z the inner, so the cell at (gx, gz) is at linear index gx * gridHeight + gz.

FieldTypeBytes
countuint16_t2
indicesuint16_t x count2 x count

Each index refers to an entry in the wall OBB array. An empty cell is a count of zero followed by no index bytes at all.

Floor triangles​

floorTriCount records, 44 bytes each.

FieldTypeBytesConvention
v0int32_t x312x128
v1int32_t x312x128
v2int32_t x312x128
normalint16_t x36FP12
padding2 zero bytes2written by the exporter, skipped by the reader

Wall OBBs​

wallOBBCount records, 64 bytes each.

FieldTypeBytesConvention
centerint32_t x312x128
axes[0]int32_t x312FP12
axes[1]int32_t x312FP12
axes[2]int32_t x312FP12
halfExtentsint32_t x312x128
flagsuint32_t4reserved, always 0

axes are the source object's local X, Y and Z in world space, in that order. The exporter does not sort them. Whichever half extent is numerically smallest is clamped to a minimum thickness of 32 units so that a flat wall still has volume, but that can be index 0, 1 or 2 depending on how the source mesh is oriented. Do not assume the thin axis is axes[2].

Caveats​

  • The engine has no grid lookup. gridWidth, gridHeight, cellSize, originX, originZ and gridCells appear nowhere outside ColbinManager itself. The grid is parsed and stored and nothing queries it yet. Earlier revisions of this page carried a world-position-to-cell code sample; it described intended behaviour, not shipped behaviour, and has been removed. The mapping the exporter uses when it populates cells is floor((x - originX) / cellSize), clamped to the grid bounds, if you want to implement the lookup against it.

Changelog​

  • Version 2: added the uniform grid over wall OBBs.
  • Version 1: floor triangles and wall OBBs only.