-
Notifications
You must be signed in to change notification settings - Fork 3
File format
There are three versions of the A3D file format which are used for different types of objects in the game: version 1 files are no longer used, version 2 files are used for map geometry (props and terrain meshes etc...), version 3 files are used for tank models (turrets and hulls).
The A3D file format is able to store: basic material data, mesh data (including coordinate, UV, normals and colour vertex buffers), submesh/surface data (with material indices), transform data and hierarchy data.
Padding is only used by version 3 models, it is calculated using:
paddingSize = (((dataLength + 3) // 4) * 4) - dataLengthVersion 2 uses null terminated strings, e.g. the strings have no length and characters are read from the stream until a null is reached (\0). Version 3 uses an int32 length field which comes before the characters with no null terminator, this is followed by padding bytes (padding calculated from string length).
The A3D file format is based around data blocks, data blocks are sections of the file which encode different data in the model such as meshes and materials.
struct DataBlock
{
int dataBlockSignature; // Identifies which datablock this is
int dataBlockLength; // This field is used to compute padding in version 3 files, other versions don't use it
// Data block specifc data goes here
};TODO
struct {
char signature[4]; // "A3D\0"
int version; // 2
RootDataBlock root;
};This contains all model data blocks.
struct RootDataBlock
{
int rootBlockSignature;
int rootBlockLength;
MaterialBlock materialBlock;
MeshBlock meshBlock;
TransformBlock transformBlock;
ObjectBlock objectBlock;
};struct A3DMaterialBlock
{
int materialBlockSignature;
int materialBlockLength;
int materialCount;
struct A3DMaterial
{
string name;
float colorR;
float colorG;
float colorB;
string diffuseMap;
} materials[materialCount];
};struct MeshBlock
{
int meshBlockSignature;
int meshBlockLength;
int meshCount;
struct Mesh
{
int vertexCount;
int vertexBufferCount;
struct VertexBuffer
{
int bufferType;
float vertices[]; // vertex size * vertex count
} vertexBuffers[vertexBufferCount];
int submeshCount;
struct Submesh
{
int faceCount;
short indices[faceCount*3]; // array of 16 bit indices
int smoothingGroups[faceCount];
short materialID;
} submeshes[submeshCount];
} mesh[meshCount];
};struct TransformBlock
{
int transformBlockSignature;
int transformBlockLength;
int transformCount;
struct Transform {
float positionX;
float positionY;
float positionZ;
float rotationX;
float rotationY;
float rotationZ;
float rotationW;
float scaleX;
float scaleY;
float scaleZ;
} transforms[transformCount];
int transformIDs[transformCount]; // Each ID corresponds to a transform component at the same index, this ID is referenced by external data blocks
};struct ObjectBlock
{
int objectBlockSignature;
int objectBlockLength;
int objectCount;
struct Object
{
string name;
int meshID;
int transformID;
} objects[objectCount];
};struct {
char signature[4]; // "A3D\0"
int version; // 3
RootDataBlock root;
};This contains all model data blocks.
struct RootDataBlock
{
int rootBlockSignature;
int rootBlockLength;
MaterialBlock materialBlock;
MeshBlock meshBlock;
TransformBlock transformBlock;
ObjectBlock objectBlock;
};struct A3DMaterialBlock
{
int materialBlockSignature;
int materialBlockLength;
int materialCount;
struct A3DMaterial
{
string name;
float colorR;
float colorG;
float colorB;
string diffuseMap;
} materials[materialCount];
byte padding[]; // depends on materialBlockLength
};struct MeshBlock
{
int meshBlockSignature;
int meshBlockLength;
int meshCount;
struct Mesh
{
string name;
float bboxMaxX;
float bboxMaxY;
float bboxMaxZ;
float bboxMinX;
float bboxMinY;
float bboxMinZ;
float unknown;
int vertexCount;
int vertexBufferCount;
struct VertexBuffer
{
int bufferType;
float vertices[]; // vertex size * vertex count
} vertexBuffers[vertexBufferCount];
int submeshCount;
struct Submesh
{
int indexCount;
short indices[indexCount]; // array of 16 bit indices
byte padding[]; // dependent on indexCount*2
} submeshes[submeshCount];
} mesh[meshCount];
byte padding[]; // depends on meshBlockLength
};struct TransformBlock
{
int transformBlockSignature;
int transformBlockLength;
int transformCount;
struct Transform {
string name;
float positionX;
float positionY;
float positionZ;
float rotationX;
float rotationY;
float rotationZ;
float rotationW;
float scaleX;
float scaleY;
float scaleZ;
} transforms[transformCount];
int transformIDs[transformCount]; // Each ID corresponds to a transform component at the same index, this ID is referenced by external data blocks
byte padding[]; // depends on transformBlockLength
};struct ObjectBlock
{
int objectBlockSignature;
int objectBlockLength;
int objectCount;
struct Object
{
int meshID;
int transformID;
int materialCount;
int materialIDs[materialCount];
} objects[objectCount];
byte padding[]; // depends on objectBlockLength
};