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

Format

Little endian.

Header

Field Type Notes
version uint32
imageInfoCount uint32

ImageInfo

imageInfoCount of these, 60 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

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

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
crc uint32
size uint32 Size of the tile data

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, and slice size bytes at offset out of the matching static.vtexN.

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:

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.