vtex_idx - themeldingwars/Documentation GitHub Wiki

Virtual texture index.

static.vtex_idx is the index for the static.vtex0 .. static.vtex6 virtual texture files. It answers two questions: which texture assets exist in the virtual texture and where they sit in it, and where an individual tile lives inside a given static.vtexN.

010 Editor Templates

Implementations

  • FauFau reads it with VTexIndex, including the FastLZ tables

Format

Little endian.

Header

Field Type Notes
version uint32 Always 1
imageInfoCount uint32

ImageInfo

imageInfoCount of these, 76 bytes each:

Field Type Notes
hash uint32[3] Three texture file hashes, see Image info hashes
transform float[9]
bounds uint16[4]
offset uint32[4]
crc uint32

The 1962 index has 4'206 of them. What transform, bounds, offset and crc mean exactly hasn't been worked out yet.

TileInfo blocks

Exactly seven blocks follow the image infos, one for each static.vtexN, in order from 0 to 6:

Field Type Notes
compressedLength uint32
compressedData byte[compressedLength] FastLZ, same as CHUNK_GEOMETRY uses

The FastLZ level is in the upper 3 bits of the first byte, plus one. All seven blocks of the 1962 index use level 2.

Each block decompresses to a flat array of 16 byte rows, with no count in front of it, so the row count is simply the decompressed length divided by 16:

Field Type Notes
offset uint64 Offset of the tile inside static.vtexN, 0xFFFFFFFFFFFFFFFF if the tile doesn't exist
crc uint32 CRC-32 of the decoded tile, see vtex
size uint32 Size of the tile data

The tables are complete, level 0 has a row for each of 1024 x 1024 tiles and every level after it a quarter of that, down to 16 x 16 at level 6:

Level Rows Existing tiles in 1962
0 1'048'576 732'743
1 262'144 185'318
2 65'536 46'839
3 16'384 11'765
4 4'096 2'958
5 1'024 745
6 256 192

So to pull a single tile out of the virtual texture, decompress the tile info block for the mip level you want, take the row for the tile, skip it if the offset is all FF, and slice size bytes at offset out of the matching static.vtexN. How the tile is decoded from there is on the vtex page.

Image info hashes

Each imageinfo entry contains three hashes, each pointing to a different texture file. The hash is a rotate-and-add over the ascii of the asset's path in the 00113000\00113473 form, i.e. the folder is the id rounded down to the nearest thousand. This is the same hash the client uses, 113473 hashes to 4264839707:

public static uint GenerateHash(int textureAssetId)
{
	string str = textureAssetId.ToString().PadLeft(8, '0');
	str = str.Substring(0, str.Length - 3) + "000" + "\\" + str;
	byte[] bytes = Encoding.ASCII.GetBytes(str);

	uint hash = 0;
	foreach (byte b in bytes)
	{
		hash = (hash << 7) | (hash >> (32 - 7));
		hash += b;
	}
	return hash;
}

// assault
uint h1 = GenerateHash(113473);
uint h2 = GenerateHash(113475);
uint h3 = GenerateHash(113476);

Since the hash is over a fixed shape of string derived from a number, it can be reversed by brute force over the plausible asset id range rather than by cracking the hash. FauFau has it as VTexIndex.HashAssetPath.