VISI (MREA Section)

Within MREA resources, the VISI section stores a PVS indexed into an octree. This PVS is used to determine visibility/occlusion between cubic sections of the area and models, scripting entities, and lights in the scene.

Layout

Data Type Description Notes
FourCC VISI magic
u32 VISI Version 0x2 in Metroid Prime.
bool Has Actors If set, the game will resolve script entity IDs for the PVS lookup
bool Unknown 2
u32 Feature count Number of static MREA meshes + script entities encoded in octree.
u32 Light count Total number of area lights encoded in octree leaves.
u32 2nd Layer Light Count Lights within total that are in the 2nd BABEDEAD layer.
u32 Entity count Number of script entities encoded in octree.
u32 Leaf size Size of octree leaf node in bytes.
u32 Light visibility node count Count of leaf nodes from light perspectives (matches light count).
u32[entityCount] Entity array Array of entity IDs mapping the octree bits to the lower 16-bits of the SCLY editor IDs.
u8[lightVisibilityNodeCount][leafSize] Light visibility node array Array of leaf node data indicating visibility of other objects from light's perspective. 2nd layer lights are listed first.
float[2][3] Octree AABB Total bounds subdivided by octree. Note: the coordinates of the AABB are in local area space (i.e. inverse-transformed with the matrix in the MREA header).
u32 Total visibility object count Number of objects per-leaf that indicate visibility from the selected octree region (static + entities + lights).
u32 Total light object count Number of objects within total that are lights.
u32 Octree length Size of octree in bytes.
u8[octreeLength] Octree data Byte-packed PVS octree data described below.

Octree Nodes

The octree data is arranged in a Z-major, depth-first hierarchy embedded with variable-length pointers to skip over children, permitting rapid child selection. Each node of the octree starts with a 1-byte header of classification bits. If at least one subdivide bit is set, the node is a branch and contains 1-7 pointers, addressed relative to the position after the pointers. One subdivision will have 1 pointer, two subdivisions will have 3 pointers, and three subdivisions will have 7 pointers. The first child pointer is implied to be 0x0. Pointer data type is specified in the header (8, 16, or 24 bits).

Bit (from LSB) Description
0 Branch Subdivide X
1 Branch Subdivide Y
2 Branch Subdivide Z
3-4 Node type
  1. Out of bounds (not used)
  2. End of hierarchy (indicates nothing is visible)
  3. Regular node (followed by branch pointers or leaf bits)
5-6 Branch pointer type
  1. 16-bit pointers
  2. 8-bit pointers
  3. 24-bit pointers

Leaf Nodes

Instead of child pointers, leaf nodes contain byte-packed bits indicating visibility. The bits are arranged from LSB to MSB per-byte. First are the bits relating static MREA geometry in-order of the first MREA sections. Next are bits relating the scripted entities in the VISI entities table.

Finally are the bits relating lights in order of the BABEDEAD section of the MREA. The 2nd layer lights are related first. Each light encodes 2-bits apiece, with the following enum represented:

Value Description
0 Not Visible
1 Visible
2 Outside Octree Bounds