DZB is used as the collision format in The Legend of Zelda: The Wind Waker. It was first introduced in The Legend of Zelda: The Wind Waker, and was mostly replaced by The Legend of Zelda: Twilight Princess, where it was only used for object collision, rather than scene collision.
The format contains no specific MAGIC, so its extension, ".dzb," is used to refer to it instead. DZB utilizes an embedded octree to accelerate collision detection by the engine and increase collision resolution.
The header of the DZB format lays out the offset of each section and the number of entries each of them has.
//0x34/52dec bytes long /*0x00*/ int NumVertices; /*0x04*/ int VerticesOffset; /*0x08*/ int NumFaces; /*0x0C*/ int FacesOffset; /*0x10*/ int NumOctreeIndexes; /*0x14*/ int IndexesOffset; /*0x18*/ int NumOctreeNodes; /*0x1C*/ int OctreeOffset; /*0x20*/ int NumGroups; /*0x24*/ int GroupsOffset; /*0x28*/ int NumProperties; /*0x2C*/ int PropertiesOffset; /*0x30*/ int Padding;
Vertices are stored as regular floating point singles.
//0xC/12dec bytes long /*0x00*/ float XPos; /*0x04*/ float YPos; /*0x08*/ float ZPos;
Faces are made up of 3 indexes into the vertex section, in addition to indexes for the group they belong to and the property they use.
//0xA/10dec bytes long /*0x00*/ short Vert1Index; /*0x02*/ short Vert2Index; /*0x04*/ short Vert3Index; /*0x06*/ short PropertyIndex; /*0x08*/ short GroupIndex;
In order to speed up collision detection, DZB uses an octree to partition parts of the mesh into separate spaces. It is split between two sections: the actual Tree and octree Indexes.
The octree is made up of branch and leaf nodes. Each group in the file that actually has collision assigned to it contains the index of the group's root leaf. From there, the tree grows until a certain condition is met. That condition is currently unknown.
Nodes have two forms, which are differentiated by a boolean, which will be named IsLeafNode. If it is false, the node is a branch and contains the indexes of other branches or leaves for each octant of the space to be subdivided. If it is true, the node is a leaf and contains the index to an index in the octree Indexes section.
//0x14/20dec bytes long /*0x00*/ const byte MagicOne = 1; /*0x01*/ bool IsLeafNode; /*0x02*/ short ParentNodeIndex; /*0x04*/ short Octant1BranchIndex; //If IsLeafNode == true, this field instead contains an index into the Octree Indexes section. All other fields after this would be filled with 0xFF. /*0x06*/ short Octant2BranchIndex; /*0x08*/ short Octant3BranchIndex; /*0x0A*/ short Octant4BranchIndex; /*0x0C*/ short Octant5BranchIndex; /*0x0E*/ short Octant6BranchIndex; /*0x10*/ short Octant7BranchIndex; /*0x12*/ short Octant8BranchIndex;
This is the index of a face for the octree to use. By some currently unknown association, this face and others related to it become part of the octant of the leaf that referenced it.
//2 bytes long /*0x00*/ short FaceIndex;
These give the faces that reference them their attributes, such as whether they trigger an exit, what sound they make when items collide with them, and how Link will interact with them. Most of the data is compressed into 3 bit fields, but there is one int tacked onto the end.
//0x10/16dec bytes long /*0x00*/ int Bitfield1; //Contains Cam ID, Exit ID, Sound ID, and PolyColor /*0x04*/ int Bitfield2; //Contains LinkNo, Wall Code, Special Code, Attribute Code Direct, and Ground Code /*0x08*/ int Bitfield3; //Contains CamMoveBG, RoomCamID, RoomPathID, and RoomPathPntNo /*0x0C*/ int CameraBehavior;
Bit field 1
|Exit ID||If this is not 0x1F, then the face triggers the exit with this index. Otherwise, the face does nothing.||0x1F00|
|Sound ID||Sets the sound that plays when Link interacts with the face.||0x7E000|
Bit field 2
|Wall Code||Sets the wall type, such as climable like a ladder or grabable like a block.||0xF00|
|Attribute Code Direct||?||0x1F0000|
|Ground Code||Sets the terrain type, such as sloped or slippery.||0x3E00000|
Bit field 3
Groups form a hierarchy that appears derived from the original structure of the model in Maya. Only the lowest groups in the hierarchy have geometry data attached to them.
In addition to the hierarchy, groups have the ability to transform, scale, and rotate their geometry, though these are rarely used in practice. Confoundingly, groups contain the only indicator of whether geometry is solid, water, or lava.
//0x34/52dec bytes long /*0x00*/ int NameOffset; /*0x04*/ float XScale; /*0x08*/ float YScale; /*0x0C*/ float ZScale; /*0x10*/ short XRotation; /*0x12*/ short YRotation; /*0x14*/ short ZRotation; /*0x16*/ short RotPadding; /*0x18*/ float XTrans; /*0x1C*/ float YTrans; /*0x20*/ float ZTrans; /*0x24*/ short ParentGroupIndex; /*0x26*/ short NextSiblingGroupIndex; /*0x28*/ short FirstChildGroupIndex; /*0x2A*/ short UnknownField1; /*0x2C*/ short UnknownField2; /*0x2E*/ short OctreeRootNodeIndex; /*0x30*/ short UnknownField3; /*0x32*/ byte TerrainType; //0 = solid ground, 1 = water, 2 = lava /*0x33*/ byte UnknownField4;