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

VIS (Visibility Graph)

VIS is an ASCII graph structure used extensively by the rendering engine to calculate occlusion culling. It plots mathematical relationships defining which room meshes are visible from any given observer room.

At a Glance

PropertyValue
Extension(s).vis
Magic SignatureNone
TypeRoom Graph
Rust ReferenceView rakata_formats::Vis in Rustdocs

File Layout

Plain ASCII, no header, no magic, no terminator. The whole file is a sequence of blocks, one per observer room:

m01aa_08c 4
  m01aa_08a
  m01aa_08b
  m01aa_07a
  m01aa_07b

An unindented line names an observer room and how many rooms it can see. The lines that follow are those rooms, one per line, each indented by exactly two spaces. The next unindented line begins the next block. Room names carry no extension and refer to the rooms in the module’s LYT.

Measured across every .vis in chitin.key: the indent is two spaces in every child line without exception, and no file contains a blank line.

Warning

Do not trust the count, and do not assume the graph is symmetric This is the counted case from counted, terminated, or neither, with the twist that the count is not reliable, so the run has to be read as if it were terminated by the indent.

Both look like invariants and neither is one.

The count disagrees with the block in a handful of shipped files, so a reader that seeks forward by the declared number rather than reading until the indent stops will desynchronise and attribute one room’s visibility to another. Read to the end of the indented run; treat the number as a hint.

A shipped file is not a symmetric graph. Hundreds of edges name a room that does not name the source back. The engine makes the relation symmetric itself, at load, by inserting each direction as it reads (see the audit below), so the loaded result is symmetric and the file is not. A reader reproducing engine behaviour has to mirror; a tool round-tripping the file must not, or it will write back edges BioWare never shipped.

One further shape occurs. A single shipped file carries an observer line with no count at all, just the room name, which is worth tolerating rather than rejecting.

Engine Audits & Decompilation

Read from Scene::LoadVisibility at 0x004568d0 in swkotor.exe. Provenance: derived, not attested. The rows below have not been separately re-derived, so they sit on the reverse-engineering queue.

Pipeline EventGhidra Provenance & Engine Behavior
Text LoadingFunction: Scene::LoadVisibility (0x004568d0)
The .vis file is executed purely as raw text. The engine continuously extracts observer and child string pairs by looping AurResGetNextLine() over the file buffer.
Silent ForgivenessFunction: Scene::LoadVisibility (0x004568d0)
If the parser extracts a room reference (either observer or child) that does not exist in the active area layout (which it verifies via a FindRoom call), the visibility entry is quietly dropped without crashing or generating logs.
Bidirectional ApplicationFunction: Scene::SetVisibility
Calling SetVisibility(room_a, room_b, 1) inherently maps both visualization paths. The function inserts room_b into room_a’s visibility list, and immediately mirrors by adding room_a to room_b’s list while executing native deduplication.
Write GenerationFunction: Scene::SaveVisibility
When generating a .vis file natively, the engine relies on an _sscanf block structure mapping to "%s%d" and uniformly pads a dual-space indent onto all child elements beneath observer headers.