Introduction
DTS is the native binary format used by the Torque engine to store shape, mesh and (optionally) sequence data. This document serves as a basic specification for the DTS file format. Very little context is given to the shape, mesh and sequence data fields read from the DTS file so it is recommended that this resource be read along with the Torque
3D source code.
The DTS file format stores most data in separate buffers for 8, 16 or 32-bit sized values in order to speed up loading
on non-Intel platforms. A DTS file can be read as shown below; after the 3 data buffers have been created in memory, they are read in interleaved order as needed to extract the desired values (see Data Buffers).
Note: that all values are stored as little-endian, so on non-Intel platforms you will have to handle perform endian conversion for 16 and 32-bit values.
DTS Format
Name | # bytes | Data Type | Description |
DTS version number | 2 | S16 | DTS version of this file. Note that the current DTS version (for files saved by Torque 3D) is 26. Most DTS exporters and the ShowToolPro tool only read/write version 24. |
Exporter version number | 2 | S16 | For tracking version of the exporter that generated this file. Can usually be ignored. |
sizeAll | 4 | S32 | Size (in 32-bit words) of the 3 data buffers (sum of 8, 16 and 32-bit data buffers). The 32-bit data buffer starts at offset 0x0. |
start16 | 4 | S32 | 32-bit word offset into the memory buffer of the start of the 16-bit data. |
start8 | 4 | S32 | 32-bit word offset into the memory buffer of the start of the 8-bit data. |
data32 | size32 | U32* | Data buffer for 32-bit values. Size (in bytes) is equal to start16*4 |
data16 | size16 | U16* | Data buffer for 16-bit values. Size (in bytes) is equal to (start8 - start16)*4 |
data8 | size8 | U8* | Data buffer for 8-bit values. Size (in bytes) is equal to (sizeAll - start8)*4 |
numSequences | 4 | S32 | Number of sequences in the shape |
sequences | numSequences * ? | Sequence | Array of numSequences Sequences - size of each sequence depends on which nodes and objects are affected etc. See Sequences for more information |
matStreamType | 1 | S8 | Type of material stream (text or binary). Should be 0x1 (binary) for DTS files |
numMaterials | 4 | S32 | Number of materials in the shape |
matNames | numMaterials * ? | S32 and char[] | Names of the materials in the shape. Each name is stored as a 4-byte length followed by the N characters in the string (terminating NULL is not included in the length or N characters). |
matFlags | numMaterials * 4 | U32 | Flags for each material* |
matReflectanceMaps | numMaterials * 4 | S32 | Index of the material to use as a reflectance map for each material* (or -1 for none) |
matBumpMaps | numMaterials * 4 | S32 | Index of the material to use as a bump map for each material* (or -1 for none) |
matDetailMaps | numMaterials * 4 | S32 | Index of the material to use as a detail map for each material* (or -1 for none) |
dummy | numMaterials * 4 | S32 | Dummy value. Only present in DTS v25. |
matDetailScales | numMaterials * 4 | F32 | Detail scale for each material* |
matReflectance | numMaterials * 4 | F32 | Reflectance value for each material* |
Note: that all material settings (beside the name) are superceded by script Material definitions in T3D.
Sequences are stored in the DTS file as follows:
Name | # bytes | Data Type | Description |
nameIndex | 4 | S32 | The name of this sequence as in index into the names array |
flags | 4 | U32 | Sequence flags |
numKeyframes | 4 | S32 | Number of keyframes in this sequence |
duration | 4 | F32 | Duration of the sequence (in seconds) |
priority | 4 | S32 | Sequence priority |
firstGroundFrame | 4 | S32 | First ground transform keyframe in this sequence (index into the groundTranslations and groundRotation arrays) |
numGroundFrames | 4 | S32 | Number of ground transform keyframes in this sequence |
baseRotation | 4 | S32 | First node rotation keyframe in this sequence (index into the nodeRotations array) |
baseTranslation | 4 | S32 | First node translation keyframe in this sequence (index into the nodeTranslations array) |
baseScale | 4 | S32 | First node scale keyframe in this sequence (index into the nodeXXXScales arrays) |
baseObjectState | 4 | S32 | First object state keyframe in this sequence (index into the objectStates array) |
baseDecalState | 4 | S32 | First decal state keyframe in this sequence (index into the decalStates array). Note that DTS decals are deprecated, and this value should be 0. |
firstTrigger | 4 | S32 | First trigger in this sequence (index into the triggers array) |
numTriggers | 4 | S32 | Number of triggers in this sequence |
toolBegin | 4 | F32 | Value representing the start of this sequence in the exporting tool's timeline (can usually by ignored) |
rotationMatters | ? | BitSet | BitSet indicating which node rotations are animated by this sequence. |
translationMatters | ? | BitSet | BitSet indicating which node translations are animated by this sequence. |
scaleMatters | ? | BitSet | BitSet indicating which node scales are animated by this sequence. |
decalMatters | ? | BitSet | BitSet indicating which decal states are animated by this sequence. Note that DTS decals are deprecated. |
iflMatters | ? | BitSet | BitSet indicating which IFL materials are animated by this sequence. |
visMatters | ? | BitSet | BitSet indicating which object's visibility is animated by this sequence. |
frameMatters | ? | BitSet | BitSet indicating which mesh's verts are animated by this sequence. |
matFrameMatters | ? | BitSet | BitSet indicating which mesh's UV coords are animated by this sequence. |
BitSets are stored in the DTS file as:
Name | # bytes | Data Type | Description |
dummy | 4 | S32 | Dummy value |
numWords | 4 | S32 | Number of 32-bit values in the BitSet |
bits | 4 * numWords | U32 | Array of numWords 32-bit values representing the bits in the BitSet |
The 3space shape data is extracted from the 3 data buffers by maintaining a pointer into each buffer, then reading from the appropriate buffer in order as shown in the table below. The code sample below demonstrates how an array of structures might be read from the 3 buffers.
struct
{
S8 valueA[4];
S32 valueB;
S32 valueC;
S16 valueD;
} Object;
...
#define checkGuard() assert((*buff32++ == guard32++) && (*buff16++ == guard16++)
&& (*buff8++ == guard8++))
...
numObjects = *buff32++;
objects.resize(numObjects);
for (S32 i = 0; i < numObjects; i++)
{
for (S32 j = 0; j < 4; j++)
objects[i].valueA[j] = *buff8++;
objects[i].valueB = *buff32++;
objects[i].valueC = *buff32++;
objects[i].valueD = *buff16++;
}
checkGuard();
The GUARD entries indicate a buffer checkpoint that verifies the buffers are being accessed correctly. Each time the GUARD entry is encountered, an incrementing value should be read from each of the 3 buffers. For example, the first GUARD should read 32-bit 0x0, 16-bit 0x0 and 8-bit 0x0, the next GUARD should read 32-bit 0x1, 16-bit 0x1 and 8-bit 0x1 and so on.
Name | Buffer | Data Type | Description |
numNodes | 32-bit | S32 | Number of nodes in the shape |
numObjects | 32-bit | S32 | Number of objects in the shape |
numDecals | 32-bit | S32 | Number of decals in the shape |
numSubShapes | 32-bit | S32 | Number of subshapes in the shape |
numIFLs | 32-bit | S32 | Number of IFL materials in the shape |
numNodeRotations | 32-bit | S32 | Number of node rotation keyframes |
numNodeTranslations | 32-bit | S32 | Number of node translation keyframes |
numNodeUniformScales | 32-bit | S32 | Number of node uniform scale keyframes |
numNodeAlignedScales | 32-bit | S32 | Number of node aligned scale keyframes |
numNodeArbScales | 32-bit | S32 | Number of node arbitrary scale keyframes |
numGroundFrames | 32-bit | S32 | Number of ground transform keyframes |
numObjectStates | 32-bit | S32 | Number of object state keyframes |
numDecalStates | 32-bit | S32 | Number of decal state keyframes |
numTriggers | 32-bit | S32 | Number of triggers (all sequences) |
numDetails | 32-bit | S32 | Number of detail levels in the shape |
numMeshes | 32-bit | S32 | Number of meshes (all detail levels) in the shape |
numNames | 32-bit | S32 | Number of name strings in the shape |
smallestVisibleSize | 32-bit | F32 | Size of the smallest visible detai level |
smallestVisibleDL | 32-bit | S32 | Index of the smallest visible detail level |
GUARD | ALL | S32, S16, S8 | Buffer checkpoint (incrementing unit in each buffer) |
radius | 32-bit | F32 | Shape bounding sphere radius |
tubeRadius | 32-bit | F32 | Shape bounding cylinder radius |
center | 32-bit | Point3F { F32 x, F32 y, F32 z } | Center of the shape bounds |
bounds | 32-bit | BoxF { Point3F min, Point3F max } | Shape bounding box |
GUARD | ALL | S32, S16, S8 | Buffer checkpoint (incrementing unit in each buffer) |
nodes | 32-bit | Node { S32 nameIndex, S32 parentIndex, S32 firstObject, S32 firstChild, S32 nextSibling } | Array of numNodes Nodes |
GUARD | ALL | S32, S16, S8 | Buffer checkpoint (incrementing unit in each buffer) |
objects | 32-bit | Object { S32 nameIndex, S32 numMeshes, S32 startMeshIndex, S32 nodeIndex, S32 nextSibling, S32 firstDecal } | Array of numObjects Objects |
GUARD | ALL | S32, S16, S8 | Buffer checkpoint (incrementing unit in each buffer) |
decals | 32-bit | Decal { S32 dummy[5] } | Array of numDecals Decals. Note that decals are deprecated. |
GUARD | ALL | S32, S16, S8 | Buffer checkpoint (incrementing unit in each buffer) |
iflMaterials | 32-bit | IflMaterial { S32 nameIndex, S32 materialSlot, S32 firstFrame, S32 firstFrameOffTimeIndex, S32 numFrames } | Array of numIFLs IflMaterials |
GUARD | ALL | S32, S16, S8 | Buffer checkpoint (incrementing unit in each buffer) |
subShapeFirstNode | 32-bit | S32 | Array of numSubShapes ints representing the index of the first node in each subshape |
subShapeFirstObject | 32-bit | S32 | Array of numSubShapes ints representing the index of the first object in each subshape |
subShapeFirstDecal | 32-bit | S32 | Array of numSubShapes ints representing the index of the first decal in each subshape |
subShapeFirstTranslucentObject | 32-bit | S32 | Array of numSubShapes ints representing the index of the first translucent object in each subshape |
GUARD | ALL | S32, S16, S8 | Buffer checkpoint (incrementing unit in each buffer) |
defaultRotations | 16-bit | Quat16 { S16 x, S16 y, S16 z, S16 Z } | Array of numNodes quaternions for default node rotations |
defaultTranslations | 32-bit | Point3F { F32 x, F32 y, F32 z } | Array of numNodes points for default node translations |
nodeRotations | 16-bit | Quat16 { S16 x, S16 y, S16 z, S16 Z } | Array of numNodeRotations quaternions for node rotation keyframes (all sequences) |
nodeTranslations | 32-bit | Point3F { F32 x, F32 y, F32 z } | Array of numNodeTranslations points for node translation keyframes (all sequences) |
GUARD | ALL | S32, S16, S8 | Buffer checkpoint (incrementing unit in each buffer) |
nodeUniformScales | 32-bit | F32 | Array of numNodeUniformScales floats for node uniform scale keyframes (all sequences) |
nodeAlignedScales | 32-bit | Point3F { F32 x, F32 y, F32 z } | Array of numNodeAlignedScales points for node aligned scale keyframes (all sequences) |
nodeArbScaleFactors | 32-bit | Point3F { F32 x, F32 y, F32 z } | Array of numNodeArbScales points for node arbitrary scale factor keyframes (all sequences) |
nodeArbScaleRots | 16-bit | Quat16 { S16 x, S16 y, S16 z, S16 w } | Array of numNodeArbScales quaternions for node arbitrary scale rotation keyframes (all sequences) |
GUARD | ALL | S32, S16, S8 | Buffer checkpoint (incrementing unit in each buffer) |
groundTranslations | 32-bit | Point3F { F32 x, F32 y, F32 z } | Array of numGroundFrames points for ground transform keyframes (all sequences) |
groundRotations | 16-bit | Quat16 { S16 x, S16 y, S16 z, S16 w } | Array of numGroundFrames quaternions for ground transform keyframes (all sequences) |
GUARD | ALL | S32, S16, S8 | Buffer checkpoint (incrementing unit in each buffer) |
objectStates | 32-bit | ObjectState { F32 vis, S32 frameIndex, S32 matFrame } | Array of numObjectStates ObjectStates |
GUARD | ALL | S32, S16, S8 | Buffer checkpoint (incrementing unit in each buffer) |
decalStates | 32-bit | S32 | Array of numDecalStates dummy integers for decal states |
GUARD | ALL | S32, S16, S8 | Buffer checkpoint (incrementing unit in each buffer) |
triggers | 32-bit | Trigger { U32 state, F32 pos } | Array of numTriggers sequence triggers (all sequences) |
GUARD | ALL | S32, S16, S8 | Buffer checkpoint (incrementing unit in each buffer) |
details | 32-bit | Detail v25- { S32 nameIndex, S32 subShapeNum, S32 objectDetailNum, F32 size, F32 averageError, F32 maxError, S32 polyCount } Detail v26+ also includes { S32 bbDimension, S32 bbDetailLevel, S32 bbEquatorSteps, S32 bbPolarSteps, F32 bbPolarAngle, bool bbIncludePoles } | Array of numDetails Details |
GUARD | ALL | S32, S16, S8 | Buffer checkpoint (incrementing unit in each buffer) |
meshes | ALL | Mesh | Array of numMeshes Meshes |
GUARD | ALL | S32, S16, S8 | Buffer checkpoint (incrementing unit in each buffer) |
names | 8-bit | char[] | Array of numNames strings, stored as N characters followed by a terminating NULL for each string. |
GUARD | ALL | S32, S16, S8 | Buffer checkpoint (incrementing unit in each buffer) |
alphaIn | 32-bit | F32 | Array of numDetails floats representing alpha-in value for each detail |
alphaOut | 32-bit | F32 | Array of numDetails floats representing alpha-out value for each detail |
Meshes are stored in the 3 data buffers as follows:
Name | Buffer | Data Type | Description |
type | 32-bit | U32 | Type of mesh |
GUARD | ALL | S32, S16, S8 | Buffer checkpoint (incrementing unit in each buffer) |
numFrames | 32-bit | S32 | Number of vertex position keyframes |
numMatFrames | 32-bit | S32 | Number of vertex UV keyframes |
parentMesh | 32-bit | S32 | Index of this mesh's parent (usually -1 for none) |
bounds | 32-bit | BoxF { Point3F min, Point3F max } | Bounding box for this mesh |
center | 32-bit | Point3F { F32 x, F32 y, F32 z } | Bounds center for this mesh |
radius | 32-bit | F32 | Bounding sphere radius for this mesh |
numVerts | 32-bit | S32 | Number of vertex positions |
verts | 32-bit | Point3F { F32 x, F32 y, F32 z } | Array of numVerts vertex positions (all keyframes) |
numTVerts | 32-bit | S32 | Number of UV coordinates |
tverts | 32-bit | Point2F { F32 u, F32 v } | Array of numTVerts UV coordinates (all keyframes) |
numTVerts2 | 32-bit | S32 | Number of 2nd UV coordinates (DTS v26+ only) |
tverts2 | 32-bit | Point2F { F32 u, F32 v } | Array of numTVerts2 2nd UV coordinates (DTS v26+ only) |
numVColors | 32-bit | S32 | Number of vertex color values (DTS v26+ only) |
colors | 32-bit | ColorI { U8 red, U8 green, U8 blue, U8 alpha } | Array of numVColors vertex colors (DTS v26+ only) |
norms | 32-bit | Point3F { F32 x, F32 y, F32 z } | Array of numVerts vertex normals |
encodedNorms | 8-bit | U8 | Array of numVerts encoded normal indices |
numPrimitives | 32-bit | S32 | Number of mesh primitives (triangles, triangle lists etc) |
primitives (v24-) | 16-bit | S16 | Array of numPrimitives 16-bit Primitive struct data { start, numElements } |
primitives (v24-) | 32-bit | U32 | Array of numPrimitives 32-bit Primitive struct data { maxIndex } |
primitives (v25+) | 32-bit | Primitive { S32 start, S32 numElements, U32 matIndex } | Array of numPrimitives Primitives |
numIndices | 32-bit | S32 | Total number of vertex indices (all primitives) |
indices (DTS v25-) | 16-bit | S16 | Array of numIndices vertex indices |
indices (DTS v25+) | 32-bit | S32 | Array of numIndices vertex indices |
numMergeIndices | 32-bit | S32 | Number of merge indices. Note that merge indices have been deprecated. |
mergeIndices | 16-bit | S16 | Array of numMergeIndices merge indices |
vertsPerFrame | 32-bit | S32 | Number of vertices in each keyframe (position or UV) |
flags | 32-bit | U32 | Mesh flags |
GUARD | ALL | S32, S16, S8 | Buffer checkpoint (incrementing unit in each buffer) |
If the mesh type is TSSkinMesh, the following data is stored in addition to the normal Mesh data:
Name | Buffer | Data Type | Description |
numInitialVerts | 32-bit | S32 | Number of intial vert positions and normals |
initialVerts | 32-bit | S32 | Array of numInitialVerts positions |
norms | 32-bit | Point3F { F32 x, F32 y, F32 z } | Array of numInitialVerts vertex normals |
encodedNorms | 8-bit | U8 | Array of numInitialVerts encoded initial normal indices |
numInitialTransforms | 32-bit | S32 | Number of initial transforms |
initialTransforms | 32-bit | MatrixF { F32 m[16] } | Array of numInitialTransforms transforms |
numVertIndices | 32-bit | S32 | Number of vertex indices |
vertIndices | 32-bit | S32 | Array of numVertIndices vertex indices |
numBoneIndices | 32-bit | S32 | Number of bone indices |
boneIndices | 32-bit | S32 | Array of numBoneIndices bone indices |
numWeights | 32-bit | S32 | Number of weights |
weights | 32-bit | F32 | Array of numWeights bone weights |
numNodeIndices | 32-bit | S32 | Number of node indices |
nodeIndices | 32-bit | S32 | Array of node indices |
GUARD | ALL | S32, S16, S8 | Buffer checkpoint (incrementing unit in each buffer) |
If the mesh type is TSSortedMesh, the following data is stored in addition to the normal Mesh data:
Name | Buffer | Data Type | Description |
numClusters | 32-bit | S32 | Number of clusters |
clusters | 32-bit | Cluster { S32 startPrimitive, S32 endPrimitive, Point3F normal, F32 k, S32 frontCluster, S32 backCluster } | Array of numClusters Clusters |
numStartClusters | 32-bit | S32 | Number of start cluster indices |
startClusters | 32-bit | S32 | Array of numStartClusters start cluster indices |
numFirstVerts | 32-bit | S32 | Number of first vertex indices |
firstVerts | 32-bit | S32 | Array of numFirstVerts first vertex indices |
numNumVerts | 32-bit | S32 | Number of numVert counts |
numVerts | 32-bit | S32 | Array of numVert counts |
numFirstTVerts | 32-bit | S32 | Number of first TVert indices |
firstTVerts | 32-bit | S32 | Array of numFIrstTVerts first TVert indices |
alwaysWriteDepth | 32-bit | S32 | Always write depth flag |
GUARD | ALL | S32, S16, S8 | Buffer checkpoint (incrementing unit in each buffer) |
|