vgeo_idx - themeldingwars/Documentation GitHub Wiki
Virtual Geometry Index
The static.vgeo_idx file is an index coupled to the static.vgeo file, and is needed to parse the data.
Both live in system/vg. The static.vgeo data is used to render geometry data for the .gtchunks.
The static.vgeo data consists of vertices, sectioned into pages.
Each page can contain up to 2048 vertices.
The system is believed to have been introduced in patch 0.6. The earliest known build with is beta-1586.
Two versions of these files are known, distinguished by the version in the static.vgeo_idx header.
These are version 1 and version 3, 1962 ships version 3.
The difference is that in version 3, data in static.vgeo is compressed with LZMA, and pages do not contain a uniform amount of data.
This results in the static.vgeo_idx containing some additional data.
The client loads the pages in FUN_012c2b40 (build 1962).
010 Editor Template
Implementations
- FauFau reads the index and decodes the pages (
VGeoIndexandVGeoPage)
Format
Little endian.
static.vgeo_idx
| Field | Type | Notes |
|---|---|---|
version |
int32 |
1 or 3 |
pageUsageBits |
uint8 |
Only in version 3, 1 when the pages are compressed |
pageCount |
int32 |
|
pages |
PageInfo[pageCount] |
|
textureCount |
int32 |
|
textures |
uint32[3][textureCount] |
Three hashes per texture path, like the images of the vtex_idx |
otherCount |
int32 |
Only in version 1 |
otherData |
uint32[otherCount] |
Only in version 1, not decoded |
PageInfo
| Field | Type | Notes |
|---|---|---|
startOffset |
uint64 |
Offset of the page in static.vgeo |
crc32 |
uint32 |
Standard zlib CRC-32 of the decoded vertex data |
numVerts |
uint16 |
0 for an empty page, the fields below are missing then |
sectionSize |
uint16 |
Not in version 1. Size of the stored page, including the stride byte |
vertIndexBitfield |
byte[256] |
Not in version 1. One bit per slot of the page, see below |
Pages
To parse a page from version 1, jump to its startOffset and read numVerts vertices of 27 bytes.
To parse a page from version 3, jump to the startOffset and slice out sectionSize bytes:
| Field | Type | Notes |
|---|---|---|
stride |
uint8 |
1 for 27 byte vertices, 0 for 23 byte vertices |
properties |
byte[5] |
LZMA properties, the lc/lp/pb byte and the dictionary size |
data |
byte[] |
Raw LZMA stream, the rest of the section |
The LZMA stream has no size in front of it, the decoded size is numVerts times the vertex size.
The CRC-32 in the index is computed over exactly these decoded bytes, so it's a good check that a page decoded properly.
The vertices are stored back to back. A vertex starts with its position as three floats, the rest of the 23 or 27 bytes isn't known yet.
The vertIndexBitfield maps the stored vertices to their slot in the page.
Bit n (byte n / 8, bit n % 8, least significant bit first) is set when slot n holds a vertex, and the stored vertices fill the set slots in order.
So the number of set bits matches numVerts.
The 1962 static.vgeo_idx has 14,814 pages with vertices, 10,243 of them with 23 byte and 4,571 with 27 byte vertices, plus 10,452 empty pages.
All of them decode to their numVerts and match their CRC-32.
Open questions
- What the bytes after the position are. Normals, UVs and a texture reference are the obvious candidates, the 4 bytes difference between the two strides suggests one optional attribute.
- What the
otherDataof version 1 is, the template guesses more CRCs.