ZDBSP nodes

From DoomWiki.org

(Redirected from ZNODES)
Under construction icon-yellow.svgThis article or section is a stub. Please help the Doom Wiki by adding to it.
A standard Doom map format level, recompiled to use the XNOD format. In this format, the SEGS and SSECTORS lumps are intentionally left empty, as all data is stored in NODES.
A standard Doom map format level, recompiled to use the XGL3 format. Similarly to the XNOD format, all data is stored in a single lump.
A small UDMF level with a few basic lumps. Compiled with the XGL3 format.

The ZDBSP nodes, also known as ZDoom nodes, are a family of related formats created in the ZDBSP node builder to support maps with more geometry elements and larger BSP trees, as well as address precision issues which create slime trails. Additionally, there are also compressed variants of each format, aiming to reduce storage space needed for large levels.

These format are identified by their magic header signature, XNOD, XGLN, XGL2 and XGL3, as well as their zlib-compressed "Z"-variants, ZNOD, ZGLN, ZGL2 and ZGL3.

Single lump[edit]

When storing BSP tree data in any of the ZDBSP formats, all of the tree is contained within a single lump, leaving the other two BSP lumps empty.

The XNOD and ZNOD versions are stored in the NODES lump, leaving SSECTORS and SEGS empty. Meanwhile, all of XGLN, XGL2, XGL3, ZGLN, ZGL2 and ZGL3 are stored in the SSECTORS lump, leaving NODES and SEGS empty.

Compression[edit]

When encountering a compressed "Z"-variant, the supporting engine must decode all the bytes following the header as a zlib stream into their respective uncompressed "X"-variants internally, before proceeding with the remaining parsing of the binary data as if it were the uncompressed counterpart.

Hardware rendering[edit]

Starting with XGLN, the ZDBSP formats are required to met the strict polygonal requirements needed for subsectors to be strictly convex, by following the same rules as the GL nodes formats.

  • The inclusion of "minisegs", segments which do not reference any linedef.
  • All segments, both real and minisegs, in a given subsector are sorted along a clockwise orientation.
  • Segments along double-sided linedefs are given a "partner" segment, that being the segment on the other side of the line.

Some hardware accelerated supporting engines may not be able to support XNOD, and may instead strictly require the hardware-friendly formats, XGLN, XGL2 or XGL3. This is the case for later versions of ZDoom and its descendant ports, which require support for the textured automap feature even in software rendering mode.

UDMF[edit]

Main article: UDMF

While the base 1.1 UDMF specification does not strictly specify which format to use for the BSP tree, the ZDBSP formats have become the de-facto standard for all UDMF capable engines. The lump is expected to be named "ZNODES" and will be parsed just the same as any other binary map format.

Support[edit]

While, historically, the use of other formats (such as GL nodes) did not see widespread adoption, the ZDBSP nodes went on to be more widely supported by various engines.

Structure[edit]

Each format is based on the previous entry in the family, with respectively named changes below, i.e. XGLN is based on XNOD with some differences, XGL2 is based on XGLN and XGL3 is based on XGL2.

Vertex (XNOD)[edit]

ZDBSP separates the BSP-generated vertices, created from segment splitting during the node building process, from the main VERTEXES lump. This frees up the main lump to only store vertices associated with the main map geometry and not BSP data. ZDBSP's vertices are also in full 32 bits fixed point fractional coordinates, helping prevent many slime trails, compared to the regular and DeePBSPV4 node format. Each vertex is 8 bytes long.

Offset Size (bytes) C99 type Description
0 4 int32_t x position
4 4 int32_t y position

Node (XNOD)[edit]

Nodes are mostly similar to the vanilla Doom format, however they are modified to support 32-bit indexes, instead of vanilla's 16-bit indexes. This removes the limit of nodes and subsectors, from 32767 each, to ~2.14 billion each. Each node is 32 bytes long.

Offset Size (bytes) C99 type Description
0 2 int16_t x coordinate of partition line start
2 2 int16_t y coordinate of partition line start
4 2 int16_t Change in x from start to end of partition line
6 2 int16_t Change in y from start to end of partition line
8 8 int16_t [4] Right bounding box
16 8 int16_t [4] Left bounding box
24 4 int32_t Right child
28 4 int32_t Left child

Subsector (XNOD)[edit]

Subsectors no longer store a starting seg index, only the number of total segs per subsector. Segments are thus required to be strictly sorted, and starting indexes are read implicitly from this sorting. Each subsector is 4 bytes long.

Offset Size (bytes) C99 type Description
0 4 int32_t Seg count

Segment (XNOD)[edit]

Segments are significantly reduced from their vanilla counterpart. These no longer store angle or offset data, requiring the supporting engine to compute both at load time. Vertex indexing is now done via 32-bit integers, instead of vanilla's 16-bit indexes. Each segment is 11 bytes long.

Offset Size (bytes) C99 type Description
0 4 int32_t Starting vertex number
4 4 int32_t Ending vertex number
8 2 int16_t Linedef number
10 1 int8_t Direction: 0 (same as linedef) or 1 (opposite of linedef)

Segment (XGLN)[edit]

Starting with XGLN, minisegs are now included in the total list of segments stored in the BSP tree, due to this and the required subsector clockwise sorting, the second vertex can be easily implied from the starting vertex of the next segment in the respective subsector. Partner segs are also included. Each XGLN segment is 11 bytes long.

Offset Size (bytes) C99 type Description
0 4 int32_t Starting vertex number
4 4 int32_t Partner seg number
8 2 int16_t Linedef number
10 1 int8_t Direction: 0 (same as linedef) or 1 (opposite of linedef)

Segment (XGL2)[edit]

The XGL2 format was devised shortly after the UDMF spec was finalized. Due to UDMF's support for more map elements than can fit in 16-bit integers, this was needed to increase the maximum supported number of linedefs in a map. Each XGL2 segment is 13 bytes long.

Offset Size (bytes) C99 type Description
0 4 int32_t Starting vertex number
4 4 int32_t Partner seg number
8 4 int32_t Linedef number
12 1 int8_t Direction: 0 (same as linedef) or 1 (opposite of linedef)

Node (XGL3)[edit]

The XNOD nodes have been enhanced in the XGL3 format to support fractional coordinates for node partition lines, via 32-bit fixed point numbers. Each XGL3 node is 40 bytes long.

Offset Size (bytes) C99 type Description
0 4 int32_t x coordinate of partition line start
4 4 int32_t y coordinate of partition line start
8 4 int32_t Change in x from start to end of partition line
12 4 int32_t Change in y from start to end of partition line
16 8 int16_t [4] Right bounding box
24 8 int16_t [4] Left bounding box
32 4 int32_t Right child
36 4 int32_t Left child

Formats overview[edit]

ZDBSP formats overview
XNOD XGLN XGL2 XGL3
Magic header string "XNOD" "XGLN" "XGL2" "XGL3"
Magic header bytes 0x584E4F44 0x58474C4E 0x58474C32 0x58474C33
Lump holding magic header NODES SSECTORS SSECTORS SSECTORS
Vertices Vertex XNOD Vertex XNOD Vertex XNOD Vertex XNOD
Nodes Nodes XNOD Nodes XNOD Nodes XNOD Nodes XGL3
Subsectors Subsectors XNOD Subsectors XNOD Subsectors XNOD Subsectors XNOD
Segments Segments XNOD Segments XGLN Segments XGL2 Segments XGL2

Sequence[edit]

Due to the structural similarity between all formats listed above, it is common for implementing engines to parse ZDBSP nodes in a single multi-parsing function, or procedure, that selects the correct segment or node structure. Thus, apart from the decompression step, any implementing engine can internally treat these formats as simply different "versions".

The following is the structure sequence for the base XNOD format, actual byte sizes may differ on the later versions.

Size Type Description
4 char[4] Magic header ID, i.e "XNOD", "ZNOD", "XGLN", "ZGLN", etc
4 int32_t Number of "old" vertices, from the main map geometry
4 int32_t Number of "new" vertices, generated from splitting segs on the BSP tree
8 * number of new vertices Vertex (XNOD) All "new" vertices
4 int32_t Number of subsectors
4 * number of subsectors Subsector (XNOD) All subsectors
4 int32_t Number of segments
11 * number of segment Segment (XNOD) All segments
4 int32_t Number of nodes
32 * number of nodes Node (XNOD) All nodes

See also[edit]

External links[edit]