|0x00||res_id||01 4E 02 00||590||00590-.AKVA|
|0x04||lev_id||01 00 00 06||3||level 3|
|0x1C||int32||1E 01 00 00||10000||array size|
|First element (black outline)|
|0x00||int32||00 00 00 00||0||index into AKBP array; BSP tree for this BNV|
|0x04||int32||00 00 00 00||0||BNV's ID (same as index in array)|
|0x08||int32||00 00 00 00||0||index into AKBA array; "side" range start|
|0x0C||int32||06 00 00 00||6||index into AKBA array; "side" range end|
|0x10||int32||FF FF FF FF||-1||index in array of child BNV|
|0x14||int32||FF FF FF FF||-1||index in array of sibling BNV|
|0x18||int32||FF FF FF FF||-1||runtime only|
|0x1C||int32||C9 00 00 00||201||size of the pathfinding grid along x in tiles|
|0x20||int32||16 00 00 00||22||size of the pathfinding grid along z in tiles|
|0x24||offset||A0 3A 47 00||00 47 3A A0||at this position starts the pathfinding grid part in the raw file|
|0x28||int32||F7 01 00 00||503||size of the pathfinding grid part in the raw file in bytes|
|0x2C||float||00 00 80 40||4.000000||tile size of the pathfinding grid|
|0x30||float||00 00 20 41||10.000000||AABB X- (AABB = Axis-aligned bounding box)|
|0x34||float||00 00 58 C1||-13.500000||AABB Y-|
|0x38||float||00 80 2A C4||−682.000000||AABB Z-|
|0x3C||float||00 40 47 44||797.000000||AABB X+|
|0x40||float||00 00 22 42||40.500000||AABB Y+|
|0x44||float||00 00 19 C4||-612.000000||AABB Z+|
|0x48||int16||FE FF||-2||grid x origin (in tiles)|
|0x4A||int16||FE FF||-2||grid z origin (in tiles)|
|0x4C||int32||00 00 00 00||0||BNV's ID again|
|0x50||int32||00 00 00 00||0||runtime only|
|0x54||int32||00 00 00 00||0||path debug info size|
|0x58||int32||00 00 00 00||0||path debug info offset (in the raw file)|
|0x5C||int32||04 00 00 00||4|| flags; used values:
|0x60||float||00 00 00 00||0.000000||if "sloped", x-component of floor normal|
|0x64||float||00 00 00 00||0.000000||if "sloped", y-component of floor normal|
|0x68||float||00 00 00 00||0.000000||if "sloped", z-component of floor normal|
|0x6C||float||00 00 00 00||0.000000||if "sloped", distance of floor plane to origin|
|0x70||float||00 00 00 00||0.000000||if "sloped", height of the BNV along the floor normal|
- BNVs are volumes that have a pathfinding grid assigned to them. The grid itself is in the raw file, while its overall parameters are in the .dat file.
- The usual volume is a right prism (or an oblique prism if the foor is sloped) but there are a few BNVs that are a bit more complex. There's not limit to the number of faces a volume can have but it's probably better to keep this number low. Most BNVs are convex but concave BNVs work too (level2 has some).
- The horizontal BNVs never overlap (that might work but it's probably useless) but a sloped BNV can overlap a horizontal one (for example some stairs that are placed in the middle of a floor, see first stairs in level 2). This means that it is possible to have ghost quads placed inside a BNV instead of on an edge. It is unknown if the engine checks that while moving inside a BNV such a ghost quad is interesected.
- It should be noted that the floor of a BNV doesn't always match the visible geometry. Common examples are sidewalks (sometimes they're included in the street's BNV which has a lower floor), stairs and the power lines in level 10.
- 0x00 - AKBP tree
- This binary space partition (BSP) tree is used to check if a point is inside the BNV. A list of BNVs that can potentially contain a point is found using the environment octree (2nd IDXA of the AKOT + OTLF). It should be noted that the BSP tree includes not only the "walls" of the BNV but the floor and ceilings too. Also, many of these "trees" are degenerate (they're lists). Actual trees occur only if the volume is not convex.
- 0x08 - AKBA range
- The "sides" of a BNV define the quads (invisible "ghost" quads, see AGQG flags and AKAA) by which an AI can transit to adjacent BNVs. These quads are used to create "connections" between the pathfinding graph's nodes. It appears that such a connection is one way only so if 2 BNVs are adjacent then each should have a transition quad that connects it to the other.
- Tipically the base of a ghost quad is in the same plane as the floor but there are some exceptions. It seems that it is possible for the ghost quad to be a above the floor (like for a sidewalk).
- 0x10 - Children and siblings
- Those occur when smaller BNVs are completely included into larger ones.
- The bigger BNV only links to its first child. If there are several children, the sibling link is used to define the series.
- Examples: lobby in CHAPTER 03 . PUZZLE PIECES (level3), big hall under main power line in CHAPTER 08 . AN INNOCENT LIFE (level10).
- It's unclear if children BNVs are really needed or used. They usually occur when the parent BNV is very tall (see level3 lobby) but due to the way the pathfinding grids work such tall BNVs might be useless (see below).
- 0x1C - Pathfinding grid
- The pathfinding grid can be seen as the projection onto the floor of (almost) all quads that intersect the BNV. This raises an interesting problem: if a polygon is high enough that a character can walk under it then it might still get projected onto the grid and result in a blocked tile. This can be seen in a couple of places in level 19 where some "furniture" has been placed on the walls and the grids under it contain blocked tiles (see the Muro fight scene for example). This does't happen always (for example the ceilings are never projected) and it's not known what rules have been used. Something along these lines seems reasonable:
- - quads that are above some height x (unknown, larger than max character's height, less than the BNV height) are projected
- - "furniture" quads are always projected (that would explain why the furniture in level 19 got projected even if it is placed higher than many ceilings)
- - "grid ignore" (see AGQG flags) quads are not projected. There are a lot of light lamps in level 9 that are placed very low and they're not projected onto the grid.
- - "danger" quads are projected but result in "danger" tiles instead of "blocked" tiles
- - quads that use "no collision" or "no character collision" are obviously not projected
- Given this it seems that there's no reason to make BNVs that are much taller than the characters.
- BNV 165 in level4 (far side of tarmac, behind the fence) has a non-zero X-Z grid size but no data in the raw file.
- Notably, that one BNV also has the 16 flag set at 0x5C (see below).
- The grid's alignment on the "floor" of the BNV's AABB is defined by the x and z offsets in tiles (at 0x48 and 0x4A).
- 0x5C - Floor and ceiling
- These value define 2 planes used as the "floor" and the "ceiling" of the BNV. It is unclear why these planes are needed as this information is already included in the BSP tree. The engine uses these values if the "sloped" bit is set to 1 (they're ignored otherwise) so they need to be correct.
- The 3 power lines in level10 have all 5 floats equal to zero even though the "sloped" bit is set. This is very likely an error as those BNVs are obviously not sloped. Due to the way computations are done BNV detection in those areas still works.
|ONI BINARY DATA|
|AKOT << Other file types >> BINA|
|AKVA : BNV Node Array|