Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Walkmesh (BWM / WOK)

Walkmeshes govern physical collision and pathfinding across an area. They dictate exactly where a character can stand, what slopes they can climb, and what physical materials block their path.


BWM Binary

The binary implementation of the Walkmesh is entirely designed to be dumped straight into memory. Instead of smoothly parsing the file piece-by-piece, the engine constantly jumps around the file using a complex array of offsets located at the very top.

At a Glance

PropertyValue
Extension(s).bwm, .wok
Magic SignatureNone standard header block
TypeMemory-Mapped Collision Net
Rust ReferenceView rakata_formats::Bwm in Rustdocs

Engine Audits & Decompilation

The following documents the engine’s exact load sequence and field requirements for Binary Walkmeshes mapped from swkotor.exe.

(Decompilation logic for this section was entirely audited and verified via native Ghidra pipeline against swkotor.exe, explicitly pulling from CSWCollisionMesh::LoadMeshBinary at 0x00597120.)

Pipeline EventGhidra Provenance & Engine Behavior
Pointer JumpingThe engine doesn’t read the file linearly from top to bottom. Instead, it uses direct memory math (pointer arithmetic) to aggressively jump between the header and the raw data payload.
Offset ExtractionThe beginning of the file contains exact byte locations the engine uses to orient itself:
+0x08 yields the total vertex_count
+0x0C..+0x18 provides the maximum limits for faces, materials, and walk-edges
+0x18..+0x24 yields adjacency boundaries
+0x3C..+0x48 stores the direct starting addresses for the geometry data
Bounding Box OffsetsThe spans immediately following (+0x48..+0x6C and +0x6C..+0x84) are reserved specifically for tracking offsets that point to the Axis-Aligned Bounding Box (AABB) collision trees.
Ignoring the Magic IDMagic bypass: Magic and version identifiers (BWM ) are actually ignored natively during the LoadMeshBinary process. It relies on a different system entirely to verify file signatures beforehand.
Read-Only FormatOne-Way Flow: Vanilla KOTOR contains strictly read-only capabilities for BWM binaries. Developers removed any functionality needed to compile or save collision data dynamically!

Tip

Orphaned Memory Gaps: The engine entirely skips reading two massive blocks of bytes off the disk: +0x24..+0x3C (24 bytes) and +0x64..+0x6C (8 bytes). For a byte-perfect roundtrip toolset, these gaps must absolutely be preserved verbatim!


BWM ASCII

For tooling purposes, BioWare engine modules support a raw ASCII readable version of the walkmesh that can be dynamically parsed at runtime at a massive performance cost.

At a Glance

PropertyValue
Extension(s).bwm (ASCII formatted)
Magic SignatureASCII Text Directives
TypeUncompiled Collision Text

Engine Audits & Decompilation

The following documents the engine’s exact load sequence and constraints for ASCII text walkmeshes mapped from swkotor.exe.

(Decompilation logic for this section was audited and verified via native Ghidra pipeline against swkotor.exe, explicitly pulling from CSWRoomSurfaceMesh::LoadMeshText at 0x00582d70.)

Pipeline EventGhidra Provenance & Engine Behavior
Searching for KeywordsThe engine scans the text file reading line-by-line to look for the specific keywords node, verts, faces, and aabb.
Strict Face FormattingEvery defined face string must strictly format exactly 8 numbers separated by spaces. Interestingly, while the engine reads the adjacency input, it immediately deletes it! The engine forces adjacency math to be physically recomputed from scratch post-load to prevent geometric errors from old assets.
Line Length LimitsThe engine will aggressively truncate or glitch if any single text line stretches beyond 256 characters (0x100 bytes).
Face ReorderingUsing the surfacemat.2da file, the engine completely shuffles the order of the faces while loading. It essentially groups every geometry face marked “walkable” at the absolute top of the array, and pushes all non-walkable geometry straight to the bottom.
Fudging the BoundariesWhen figuring out the Axis-Aligned Bounding Box (AABB) limits, the text loader artificially stretches the box outwards by roughly 0.01 across every axis. Due to the face reordering mentioned above, the engine also has to build a temporary remap table under the hood just to keep track of where everything moved!

Warning

Because the ASCII face-reordering mechanism radically shuffles the root array indexes from walkable to unwalkable clusters via the LoadMeshText routine, it is impossible to do a clean 1-to-1 binary-to-ASCII-to-binary round trip of a KOTOR walkmesh without completely losing the original face indexing format!