Skip to content

Instantly share code, notes, and snippets.

@jamesu
Last active August 11, 2026 19:34
Show Gist options
  • Select an option

  • Save jamesu/da7e70d62ee1bb6dde82301ffad3b39a to your computer and use it in GitHub Desktop.

Select an option

Save jamesu/da7e70d62ee1bb6dde82301ffad3b39a to your computer and use it in GitHub Desktop.
A Spec of Torque Shader Engines "atlas" terrain file format

Atlas File Format Specification

Torque Shader Engine, through resource version 140.

NOTE: this spec was originally written with Google Gemini, and later refined by implementing it into TorqueViewer and correcting against reference file data. Further fixes were added using GPT-4.6.

Overview

Atlas files are binary files used for paged terrain storage. They contain one or more Tables of Contents (TOCs), each holding chunk-reference records called stubs. The referenced chunks contain geometry, texture, or configuration payloads that may be loaded independently.

A single .atlas file can contain TOCs for geometry, opacity maps, shadow maps, and configuration data. All TOCs form a contiguous prefix, followed by the referenced chunk data. Chunk order is independent of stub order.

Highest resource payload version documented here: 140.

Geometry TOCs additionally serialize mGoalBatchSize before the common parent TOC fields. The resource version controls stub and chunk fields such as bounds, morph ordering, and stored normals.

Scope and evidence

This document primarily describes the multi-resource .atlas container. Section 9 separately specifies the older .chu geometry and .tqt texture formats that can be converted into Atlas resources.

The v140 Atlas framing and layouts are confirmed by arcticBlended.atlas. Historical format definitions establish the pre-v140 geometry layouts and the CHU and TQT layouts.

For Atlas resource versions through 140, the generic file, TOC, stub-base, and resource-frame serialization is version-independent. Geometry payload changes occur at versions 101, 120, 130, and 140. Texture and config stubs/chunks have no known version-dependent branches through 140 and therefore retain the layouts documented in §§1b, 1c, 4, and 5.

Fields are serialized individually with no implicit C/C++ structure padding. Numeric values in the examined files and historical Torque streams are little-endian.

0. File-level structure

Order Type / size Contents
1 U32 Magic 0x534C5441 (ATLS in little-endian byte order)
2 U8 NUM_TOCs, the number of TOCs that follow
3 Variable TOCs 0 through NUM_TOCs-1; see §1
4 Variable Chunk data region, beginning after the last TOC stub; see §2

TOC and chunk order

TOC slot indices follow the serialized TOC order and are zero-based. Chunk frames do not have to follow stub order, be grouped by TOC, or occupy a contiguous region. Each stub's offset and length are authoritative.

Some Atlas writers arrange chunks in a separately selected physical order to improve access locality. That ordering information is not serialized as part of a stub and cannot be reconstructed from the TOC alone.

1. Table of contents block

Each TOC block is self-contained within the TOC region. The following layout applies to every TOC:

Order Part Serialized layout
1 Type tag tagLength:U8, followed by kindTag[tagLength]
2 Type-specific prefix Zero or more fields selected by kindTag
3 Common TOC body treeDepth:U32, stubCount:U32, csmVersion:U32, followed by stubs[stubCount]

kindTag contains exactly tagLength bytes and has no trailing NUL. The known canonical tag spellings are listed below.

csmVersion, formatVersion, and resourceVersion refer to the same serialized version value.

Type tag and prefix

kindTag Bytes between kindTag and the common TOC body
Geom mGoalBatchSize:U32
Tex None
Config None

Common TOC body

Order Type Field Meaning
1 U32 treeDepth Levels numbered 0..treeDepth-1; zero for the observed Config TOC
2 U32 stubCount Number of immediately following stubs
3 U32 csmVersion Resource stub/chunk format version
4 Variable stubs stubCount sequential type-specific entries

Observed v140 TOC values in arcticBlended.atlas:

Tag Prefix treeDepth stubCount csmVersion
Geom mGoalBatchSize=1500 4 85 140
Tex — 3 21 140
Tex — 5 341 140
Config — 0 1 140

The complete quadtree counts are consistent: depth 4 gives 85 stubs, depth 3 gives 21, and depth 5 gives 341. Config is not a quadtree, so its count is not derived from treeDepth.

The file position of a stub is not stored in the stub.

1a. Geometry resource stub (AtlasResourceGeomTOC::StubType)

Order Type Field Versions Meaning
1 U32 offset All Absolute file offset to chunk data
2 U32 length All Complete chunk length
3 U32 generation All Modification counter
4 F32 pos.x <101 Position X used before version 101
5 F32 pos.y <101 Position Y used before version 101
4 Box3F mBounds >=101 Six F32 values: minimum XYZ, then maximum XYZ
5 U8 sentinel >=101 Must equal 0xD0
Version Serialized size
<101 20 bytes
>=101 37 bytes

For version 101 and later, 0xD0 is the final byte of the geometry stub. It does not mark the end of the referenced geometry chunk.

1b. Texture resource stub (AtlasResourceTexTOC::StubType)

Order Type Field Meaning
1 U32 offset Absolute file offset to chunk data
2 U32 length Complete chunk length
3 U32 generation Modification counter

Serialized size: 12 bytes. Quadtree position and resource dependencies are derived from context rather than serialized in this record.

1c. Config resource stub (AtlasResourceConfigTOC::StubType)

Order Type Field Meaning
1 U32 offset Absolute file offset to chunk data
2 U32 length Complete chunk length
3 U32 generation Modification counter
4 char[8] name Fixed-width, NUL-padded identifier

Serialized size: 20 bytes. Config TOCs are named lists rather than quadtrees.

Quadtree node indexing within a TOC

The stub array stores complete tree levels consecutively, beginning with the root. Within level L, coordinates are linearized with X as the major axis and Y as the minor axis.

nodeCount(d) = 0x55555555 & ((1 << (d*2)) - 1)
             = sum of 4^level for level 0..d-1

nodeID(level, x, y) = nodeCount(level) + (x << level) + y

2. Chunk data region

Every stub references one framed chunk. Frames may appear in any physical order; the TOC references, rather than adjacency or stub order, locate them.

A stub's offset points at the beginning of this frame, and its length covers the complete frame:

Order Type / size Field Meaning
1 U32 outerMarker ATSP
2 U32 bodySize Resource payload byte count only
3 U32 typeHead Resource-specific head marker
4 bodySize bytes body Resource payload; see §§3–5
5 U32 typeTail Resource-specific tail marker

Therefore stub.length == bodySize + 16. The next framed chunk can begin immediately after typeTail; this was observed in arcticBlended.atlas.

Confirmed first geometry frame at file offset 0x1E1A:

Bytes Field Decoded value
41 54 53 50 outerMarker ATSP
93 74 05 00 bodySize 0x57493 (357523)
61 67 63 68 typeHead agch
Variable Body Geometry resource payload
61 67 63 74 typeTail agct

Its TOC reference length is 0x574A3 (357539), exactly bodySize + 16.

Atlas chunk boundaries and sentinels

Every Atlas chunk frame ends with its resource-specific typeTail. This tail is the final U32 of the complete frame and is not included in bodySize. The tail begins exactly bodySize bytes after the end of typeHead.

Chunk kind Frame begins with Body begins after Final field inside body Frame ends with
Geometry <120 ATSP agch No body sentinel; end is determined by bodySize agct
Geometry >=120 ATSP agch U32 0xCEFEDEEF agct
Texture ATSP TexH No body sentinel; encoded image ends at bodySize TexT
Config ATSP CfgH No body sentinel; final entry ends at bodySize CfgT

The serialized marker values are:

Scope Position FourCC U32 value
All chunks Frame start ATSP 0x50535441
Geometry Body head agch 0x68636761
Geometry Frame end agct 0x74636761
Texture Body head TexH 0x48786554
Texture Frame end TexT 0x54786554
Config Body head CfgH 0x48676643
Config Frame end CfgT 0x54676643

Texture and config markers are confirmed by arcticBlended.atlas.

Geometry and Config resource bodies begin with previousChunk (U32), an absolute offset to the previous chunk used for history/recovery, or zero for the first chunk. Texture bodies begin directly with their one-byte image format and do not contain previousChunk.

3. Geometry chunk (AtlasGeomChunk)

previousChunk is the first U32 in the payload. Stub offset and length are stored in the TOC and are not repeated in the body.

Geometry payload order

Order Type / size Field Versions
1 U32 previousChunk All
2 Box3F (24 bytes) mBounds >=120
3 U32 mIndexCount All
4 U32 mSkirtSkipCount All
5 mIndexCount × U16 mIndex All
6 U32 mVertCount All
7 Version-dependent Vertices All
8 Box3F (24 bytes) mBounds 101–119 only
9 U8 colFlag >=120
10 Conditional Collision data >=120 and colFlag == 0xDF
11 U32 postColSentinel >=120; must equal 0xCEFEDEEF

Versions below 101 do not serialize chunk bounds; they must be calculated from the decoded mesh.

For version 120 and later, postColSentinel is the final four bytes of the geometry body, whether or not collision data is present. The geometry frame tail agct follows immediately after it. Geometry bodies before version 120 have no internal ending sentinel; bodySize locates the following agct tail.

Index data

Type / count Field Meaning
U32 mIndexCount Number of U16 indices
U32 mSkirtSkipCount Number of trailing skirt indices
mIndexCount × U16 mIndex Triangle-list vertex indices

mIndexCount - mSkirtSkipCount is the non-skirt index count. The remaining indices are skirt triangles used for LOD blending.

Vertex data

Every vertex begins with these fields:

Order Type Field
1 3 × F32 point.x, point.y, point.z
2 2 × F32 texCoord.x, texCoord.y

Morph-field order depends on the version:

Version Following fields, in serialized order
<130 pointMorphOffset.x/y/z, then texMorphOffset.x/y
130–139 texMorphOffset.x/y, then pointMorphOffset.x/y/z
>=140 texMorphOffset.x/y, pointMorphOffset.x/y/z, then normal.x/y/z
Version Bytes per vertex Notes
<101 40 Point, texture coordinate, and both morph offsets
101–119 40 Bounds remain per chunk, not per vertex
120–129 40 Collision data follows the complete vertex array
130–139 40 Morph order swapped; same size
>=140 52 Adds three normal floats

For versions below 140, normals are not serialized and normalize to (0,0,1). mTCBounds is not serialized.

Collision data

colFlag Meaning
0xDF Collision block is present
0x0F No collision block

When collision is present:

Order Type / count Field Meaning
1 U32 mColTreeDepth Collision quadtree depth, commonly 4
2 nodeCount(mColTreeDepth) × {F32,F32} mColTree Per-node minimum and maximum triangle Z
3 U32 mColOffsetCount Number of bin offsets
4 mColOffsetCount × U16 mColIndicesOffsets Offsets into mColIndicesBuffer
5 U32 mColIndexCount Number of collision-index entries
6 mColIndexCount × U16 mColIndicesBuffer Triangle offsets into mIndex; each offset selects three consecutive vertex indices

Triangle lists within each bin are terminated by 0xFFFF; these values end individual collision-bin lists, not the chunk. Regardless of colFlag, every version-120+ geometry body ends with U32 0xCEFEDEEF, followed by the outer frame tail agct.

4. Texture chunk (AtlasTexChunk)

Order Type / size Field Meaning
1 U8 mFormat Image encoding identifier
2 Remaining body bytes Image data Complete encoded image stream

The encoded image occupies every remaining byte of the declared body. There is no texture-body footer or sentinel. The frame-ending U32 TexT follows at the first byte after the body.

mFormat Encoding Payload
0 JPEG Lossy image without stored mipmaps
1 PNG Lossless image without stored mipmaps
2 DDS DDS magic, DDS_HEADER, optional DX10 extension, pixels and mipmaps

A double-sized tile may contain both an opacity map and lightmap, as identified by the owning texture TOC.

Texture color-channel interpretation

JPEG and PNG retain their standard encoded channel definitions. However, some Atlas content was produced from bitmap data using BGR or BGRA component order. A standard decoder still returns components in RGB or RGBA positions, but the decoded red and blue values may therefore be semantically reversed for that Atlas content.

Encoded payload Channel interpretation after decoding
JPEG/PNG with normal RGB source order Use decoded R,G,B[,A] directly
JPEG/PNG produced from BGR/BGRA bitmap data Convert decoded B,G,R[,A] to R,G,B[,A]
DDS Use the DDS pixel-format masks or DXGI format; do not infer BGR order from the Atlas convention

This is an Atlas content convention rather than a change to the JPEG or PNG formats. An incorrect interpretation is readily visible as a red/blue swap, often giving terrain an excessive blue tint.

Texture-tree orientation

Atlas texture placement reflects one tree axis relative to terrain geometry. The reflection applies to the complete virtual texture, not independently to the contents of arbitrary tiles.

For texture level L, let N = 2^L. If a geometry node maps to coordinates (xL,yL) at that texture level, its texture stub and local coordinates are:

Value Mapping
Texture stub X N - 1 - xL
Texture stub Y yL
Local U N * texCoord.x - yL
Local V N * texCoord.y + xL + 1 - N

When geometry and texture levels differ, xL and yL are the geometry-node coordinates projected to level L. The stub-X and local-V relations describe the same reflected tree axis.

5. Config chunk (AtlasConfigChunk)

Order Type / size Field Meaning
1 U32 previousChunk Previous chunk offset, or zero
2 U32 entryCount Number of key/value pairs
3 Repeated entryCount times Entries Each entry uses the layout below
Entry order Type / size Field Meaning
1 U32 keyLength Key byte count
2 keyLength bytes key Key bytes; no trailing NUL is included
3 U32 valueLength Value byte count
4 valueLength bytes value Value bytes; no trailing NUL is included

Notes:

  • Config chunks are not quadtrees and have no level/position.
  • Entries are stored newest first.
  • Config bodies have no internal footer or sentinel. After the final value (or after entryCount when it is zero), the frame-ending U32 CfgT follows at the declared body boundary.

6. Stub indexing and stub references

The stub array is divided into consecutive level ranges. Level L contains 4^L entries, and its first entry follows every entry from levels 0 through L-1. Coordinates within the level use x * 2^L + y; coordinate bits are not interleaved.

totalStubs = 0x55555555 & ((1 << (d*2)) - 1)
base       = 0x55555555 & ((1 << (level*2)) - 1)
index      = base + (x << level) + y

Depth-5 example:

Level Nodes at level Cumulative stubs
0 1 1
1 4 5
2 16 21
3 64 85
4 256 341

The root (0,0,0) has index 0. At the highest level, use base + (x << (treeDepth-1)) + y.

The chunk for stub index i is located through its TOC entry:

Type Field Meaning
U32 offset Absolute file offset to the chunk
U32 length Complete chunk byte length

The referenced data begins at offset, spans length bytes, and includes the complete outer frame described in §2.

7. Version history

Version Geometry format change
101 Adds mBounds to geometry stubs and adds chunk bounds after the vertex array. Earlier stubs contain two position F32 values, and earlier chunks calculate bounds from mesh data.
120 Moves chunk bounds after previousChunk; adds collision flag/data and mandatory 0xCEFEDEEF footer.
130 Swaps the serialized order of point- and texture-morph offsets.
140 Adds three F32 normal components per vertex.

Canonical interpretation of earlier versions

The following rules describe the data implied by fields omitted from earlier versions. They allow every documented version to be represented with the v140 geometry field set without changing the serialized layout.

Source version Canonical interpretation
All through 140 The common ATSP framing and resource markers apply unchanged.
<101 Bounds are derived from the vertices; the derived bound supplies both the canonical stub bound and chunk bound.
101–119 The chunk bound is the value serialized after the vertex array.
<120 Collision data is absent. The v120 footer has no serialized counterpart.
<130 The first morph vector is pointMorphOffset; the second is texMorphOffset.
<140 The canonical normal for the omitted field is (0,0,1).
Texture/config through 140 Their serialized layouts are version-independent.

8. Complete file layout example

Confirmed prefix of arcticBlended.atlas (4 TOCs):

Offset Contents
0x0000 Magic ATLS
0x0004 U8 NUM_TOCS = 4
0x0005 tagLength=4, kindTag="Geom"
0x000A mGoalBatchSize=1500, treeDepth=4, stubCount=85, formatVersion=140
0x001A First geometry stub
0x0C63 End of 85 v140 geometry stubs; tagLength=3, kindTag="Tex"
0x0C67 treeDepth=3, stubCount=21, formatVersion=140; no geometry prefix
0x0C73 First texture stub
0x0D6F End of 21 12-byte texture stubs; tagLength=3, kindTag="Tex"
0x0D73 treeDepth=5, stubCount=341, formatVersion=140
0x0D7F First texture stub
0x1D7B End of 341 12-byte texture stubs; tagLength=6, kindTag="Config"
0x1D82 treeDepth=0, stubCount=1, formatVersion=140
0x1D8E Config ChunkRef, followed by fixed char[8] name schema
0x1DA2 End of all confirmed TOCs

All four TOCs and all 448 referenced frames in this sample are structurally consistent. Their current chunk references form a contiguous region from the first chunk through the exact end of the file. Contiguity is an observed property of this file, not a requirement imposed on every Atlas file.

9. CHU and TQT import formats are not Atlas files

CHU and TQT are standalone import formats. They are not older revisions of the Atlas container, and CHU version 400 is unrelated to Atlas resource version 140. All numeric fields below are little-endian and tightly serialized.

9a. Format identification

Bytes Format Contents
41 54 4C 53 Atlas (ATLS) Multi-resource TOCs and ATSP chunks
43 48 55 33 CHU (CHU3) One quantized geometry tree
74 71 74 00 TQT (tqt\0) One DDS texture tree

CHU/TQT have no Atlas TOCs, ATSP frames, generation counters, or history links. Their offsets refer directly to CHU chunks or TQT tiles and are not Atlas chunk-frame offsets.

9b. CHU v400

CHU contains one geometry hierarchy and no texture/config data.

Serialized CHU format

CHU header — 28 bytes:

Offset Type Field Meaning
0x00 U32 fourCC CHU3
0x04 S16 version Must be 400
0x06 S16 treeDepth Geometry-tree levels
0x08 F32 baseMaxError Probable LOD-error value; exact use is unconfirmed
0x0C F32 verticalScale World Z units per quantized unit
0x10 F32 leafDimensions World X/Y width of one leaf chunk
0x14 U32 chunkCount Number of following stubs
0x18 U32 colTreeDepth Collision-tree depth used by flagged chunks

Expected relationships:

Value Formula / rule
chunkCount nodeCount(treeDepth) for a complete tree
Terrain width/height leafDimensions * 2^(treeDepth-1)
leafDimensions Finite and positive
verticalScale Normally finite and positive

CHU stub — 37 bytes, repeated chunkCount times immediately after the header:

Relative offset Type Field Meaning
0x00 U32 sentinel Must be 0xDEADBEEF
0x04 S32 label Logical node label
0x08 4 × S32 neighbors Inferred same-level neighbor labels; direction order unknown
0x18 U8 level Root is level 0
0x19 S16 x Node X coordinate
0x1B S16 y Node Y coordinate
0x1D S16 min Inferred quantized conservative minimum Z
0x1F S16 max Inferred quantized conservative maximum Z
0x21 U32 chunkOffset Absolute offset to 0xBEEF1234 chunk sentinel

Stub records may be physically unordered. Labels identify logical tree nodes and must be unique across the complete tree. Negative neighbor values most likely mean “no neighbor”; the direction represented by each neighbor-array position is not established. Stub min and max most likely contain conservative Z bounds in units scaled by verticalScale.

CHU chunk — structurally sized, with no length prefix:

Order Type/count Field Rule
1 U32 sentinel Must be 0xBEEF1234
2 U16 vertCount Number of quantized vertices
3 vertCount × 4 × S16 vertices Per vertex: x,y,z,morph
4 S32 indexCount Must be non-negative
5 indexCount × U16 indices Geometry indices
6 U32 triCount Probable source triangle count; exact use is unconfirmed
7 U8 colDataFlag Must be 0 or 1
8 conditional Collision block Present only when flag is 1
9 U32 footer Must be 0xB1E2E3F4

The U32 footer 0xB1E2E3F4 is always the final field of a CHU chunk. It follows colDataFlag directly when the flag is zero, or follows the complete collision block when the flag is one. CHU chunks have no length field and no additional tail after this footer.

CHU collision block (colDataFlag == 1):

Order Type/count Field Rule / likely meaning
1 nodeCount(colTreeDepth) × {S16,S16} colTreeNodes Inferred quantized min/max Z
2 U32 collisionMark Must be 0xB33FD34D
3 colGridCount × U16 colOffsets Likely U16-element offsets into the buffer
4 U32 bufferSize Number of following U16 entries
5 bufferSize × U16 colIndexBuffer Likely triangle IDs; 0xFFFF probably terminates a cell

0xB33FD34D separates the collision-tree nodes from the collision-grid data; it does not end the CHU chunk. Likewise, any 0xFFFF values terminate individual collision-grid lists rather than the chunk itself. The enclosing CHU chunk still ends only at footer 0xB1E2E3F4.

Derived collision value Expression
Collision-node count nodeCount(colTreeDepth)
Collision-grid width 2^(colTreeDepth-1)
Collision-grid cell count 2^(2*(colTreeDepth-1))

When colDataFlag is 1, colTreeDepth must be nonzero so that the derived collision dimensions are defined. The exact token semantics of colOffsets and colIndexBuffer, and their direct equivalence to Atlas collision data, are not established.

Mapping CHU to Atlas geometry

The CHU hierarchy maps to one Atlas geometry TOC. Atlas node (level,x,y) uses CHU label nodeID(level,y,x), preserving the CHU/Atlas X/Y transpose.

Atlas geometry property CHU source or mapping
treeDepth CHU treeDepth
stubCount CHU chunkCount
mGoalBatchSize No CHU equivalent; selected when an Atlas file is written
Terrain width and height leafDimensions * 2^(treeDepth-1)
Chunk width at level L leafDimensions * 2^((treeDepth-1)-L)
Chunk origin Chunk width multiplied by stub X and Y
generation and previousChunk No CHU equivalent; initialize to zero

For each vertex, let size be the chunk width and origin its world-space XY origin:

Atlas vertex field CHU mapping
point.x ((x / 16384)*0.5 + 0.5)*size + origin.x
point.y ((y / 16384)*0.5 + 0.5)*size + origin.y
point.z z * verticalScale
texCoord.x point.y / terrainHeight
texCoord.y 1 - point.x / terrainWidth
pointMorphOffset (0, 0, morph*verticalScale)
texMorphOffset (0, 0)
normal (0, 0, 1)

Quantized X/Y values outside [-16384,+16384] are retained because they may represent skirts or overlap. Geometry indices map directly and must refer to existing vertices. CHU has no confirmed Atlas mSkirtSkipCount equivalent, so the canonical mapping uses zero.

Each mapped chunk bound contains its own decoded vertices and the bounds of its four children. Consequently, bounds are derived from the leaves toward the root, then stored identically in the Atlas stub and chunk. The mapped stub uses sentinel 0xD0. CHU collision is not field-compatible with Atlas collision; a mapping either regenerates Atlas collision from geometry or represents the chunk without Atlas collision data.

9c. TQT

TQT contains one texture hierarchy and no geometry/config data.

Serialized TQT format

TQT header — 16 bytes:

Offset Type Field Meaning
0x00 U32 fourCC tqt\0
0x04 U32 version TQT format version; no version-dependent layouts are known
0x08 U32 treeDepth Texture-tree levels
0x0C U32 tileSize Inferred intended square top-mip size

The header is followed immediately by:

Type/count Field Meaning
nodeCount(treeDepth) × U32 offsets Absolute tile offsets

The offset table is ordered by tree level and uses transposed horizontal coordinates: logical node (level,x,y) uses entry nodeID(level,y,x).

TQT tile at each referenced offset:

Relative offset Type/count Field Meaning
0x00 U32 chunkSize DDS byte count; excludes this U32
0x04 chunkSize bytes ddsBytes Complete stream beginning with DDS

A TQT tile is length-delimited and has no ending sentinel. Its final byte is the final byte of ddsBytes, so the complete tile range is [tileOffset, tileOffset + 4 + chunkSize).

The DDS header supplies dimensions, pixel format, mip count, and payload bounds. tileSize most likely describes the intended square top-mip dimension; the DDS header is authoritative if the values disagree.

Mapping TQT to Atlas textures

TQT maps to one Atlas texture TOC. It contains no field identifying the tree as an opacity or shadow map, so the default mapping is a base-terrain texture tree.

Atlas texture property TQT source or mapping
treeDepth TQT treeDepth
stubCount nodeCount(treeDepth)
Stub (level,x,y) Logical tree position after the table-coordinate transpose
Texture encoding DDS (mFormat=2)
Texture payload Exact TQT ddsBytes
Stub generation No TQT equivalent; initialize to zero

9d. CHU/TQT companion convention

CHU and TQT contain no serialized cross-reference to each other. By convention, a same-directory TQT with the same filename stem supplies textures for a CHU; extension matching is case-insensitive. The pair maps to one Atlas geometry TOC and one Atlas texture TOC. Either file remains independently meaningful when no companion exists.

The TQT DDS stream maps directly to an Atlas texture chunk with mFormat=2. Transcoding it to JPEG or another Atlas texture encoding is optional and is not part of either source format.

9e. Structural validity and consistency

The following conditions make the serialized structure invalid:

Condition Requirement
Magic and sentinels Must equal their values specified above
CHU indexCount Must be non-negative
CHU colDataFlag Must be 0 or 1
Counts and referenced ranges Every implied byte range must lie wholly within the file
CHU logical labels Must be unique and cover the complete declared tree
TQT tile payload Must begin with DDS and contain a complete DDS stream
Distinct TQT tile ranges Must not partially overlap

Multiple nodes may contain identical offsets, in which case they reference the same chunk or tile. Physical order, monotonic offsets, adjacency, and complete coverage through EOF are not format requirements.

The following are consistency checks rather than structural requirements, because the exact semantics of these fields are not fully established:

Comparison Interpretation
CHU stub min/max versus decoded bounds A difference may indicate conservative bounds or an incorrect interpretation
CHU triCount versus the index-derived triangle count A difference may indicate CHU-specific triangle accounting
TQT tileSize versus DDS dimensions The DDS header defines the encoded image dimensions

10. Field definitions summary

Primitive types

Type Definition
U8 8-bit unsigned integer
U16 16-bit unsigned integer
U32 32-bit unsigned integer
S16 16-bit signed integer
S32 32-bit signed integer
F32 32-bit IEEE-754 floating-point value

Composite types

Type Fields Meaning
Point2F x:F32, y:F32 Floating-point 2D point
Point2I x:S32, y:S32 Integer 2D point
Point3F x:F32, y:F32, z:F32 Floating-point 3D point
Box3F min:Point3F, max:Point3F 3D bounding box
RectF point:Point2F, extent:Point2F 2D region

Canonical geometry vertex (GFXAtlasVert2)

These are the logical geometry-vertex fields represented by the versioned serialization in §3. Earlier versions omit normal but otherwise represent the same fields in a different order where noted.

Field Type Meaning
point Point3F 3D vertex position
texCoord Point2F Texture coordinate
texMorphOffset Point2F Texture-coordinate morph offset
pointMorphOffset Point3F Position morph offset
normal Point3F Surface normal, serialized from v140
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment