Skip to content
Jasper St. Pierre edited this page Jul 28, 2018 · 36 revisions

This page describes some of the animation formats used on the BMD and BDL model files.

Standard Header


This header is found at the beginning of all animation files.

//0x20/32 bytes long
//Note: Strings are not null terminated
/*0x00*/ char[4] Magic; // "J3D" followed by a number, usually 1
/*0x04*/ char[4] StudioType; // File type followed by a number, usually 1
/*0x08*/ int fileSize;
/*0x0C*/ int numChunks; //If numChunks == 2, then there is an SVR3 chunk before the actual data. See below

SVR3

Some animation types have a null chunk called SVR3 before the chunk containing the actual data. It consists of the string SVR3 followed by 0x0C/12 null bytes.

Even if there is no SVR3 chunk, there is still a field of 0x10/16 null bytes between the end of the standard header and the data chunks.

//0x10/16 bytes long
/*0x00*/ string "SVR3";
/*0x04*/ byte[12] nullBytes;

BCK (Bone Animation)


ANK1 Header

//0x24/36 bytes long, padded out to 0x40/64 bytes
/*0x00*/ string "ANK1";
/*0x04*/ int ank1Size;
/*0x08*/ byte flag;
/*0x09*/ byte angleMultiplier;
/*0x0A*/ short animLength;
/*0x0C*/ short jointAnimationEntryCount; //One for each bone in the model
/*0x0E*/ short scaleFloatBankEntryCount;
/*0x10*/ short rotationShortBankEntryCount;
/*0x12*/ short translateFloatBankEntryCount;
/*0x14*/ int jointAnimationEntriesOffset;
/*0x18*/ int scaleFloatBankOffset;
/*0x1C*/ int rotationShortBankOffset;
/*0x20*/ int translateFloatBankOffset;

Joint Animation

Each bone in the target model has one JointAnimation entry. JointAnimation entries in BCKs are divided into nine Keyframes:

//0x36/54 bytes long
/*0x00*/ Keyframe scaleX;
/*0x06*/ Keyframe rotX;
/*0x0C*/ Keyframe transX;

/*0x12*/ Keyframe scaleY;
/*0x18*/ Keyframe rotY;
/*0x1E*/ Keyframe transY;

/*0x24*/ Keyframe scaleZ;
/*0x2A*/ Keyframe rotZ;
/*0x30*/ Keyframe transZ;

Each Keyframe handles the X, Y, or Z component of scaling, rotation, or translation. The Keyframes themselves are laid out like this:

Keyframe

//0x6/6 bytes long
/*0x00*/ short keyframeCount; //Number of keyframes in this subentry
/*0x02*/ short startingIndex; //Starting index of data in relevant bank
/*0x04*/ short unknownShort; //Either 0 or 1

Databanks

The float and short banks are made up of their respective data types, but they follow a common structure.

Each bank begins with a default value: 1.0f for scale, 0 for rotation, and 0.0f for translation. This value does not have the structure outlined below - it is only the value. After this default value, the entries in the bank follow this format:

Databank

//DataType.Length * 3 bytes long
var Time;
var Value;
var Tangent;

The decision whether to read Time/Value/Tangent instead of just Value can be made by looking at the Keyframe. If it has a frame count of 1 and an index of 0, then it will use the default value at the beginning of the bank.

BTK (Texture Animation)


TTK1 Header

// 0x60/96 bytes long
/*0x00*/ char[4] Magic_TTK1;
/*0x04*/ int TTK1Size;
/*0x08*/ byte Flag; // Assuming from ANK1!
/*0x09*/ byte AngleMultiplier; // Assuming from ANK1!
/*0x0A*/ short AnimLength;
/*0x0C*/ short TextureAnimationEntryCount; // 3 for each material
/*0x0E*/ short ScaleBankCount;
/*0x10*/ short RotationBankCount;
/*0x12*/ short TranslationBankCount;
/*0x14*/ int TextureAnimationEntriesOffset;
/*0x18*/ int RemapTableOffset;
/*0x1C*/ int StringTableOffset;
/*0x20*/ int TextureIndexTableOffset;
/*0x24*/ int TextureCenterTableOffset;
/*0x28*/ int ScaleFloatBankOffset;
/*0x2C*/ int RotationShortBankOffset;
/*0x30*/ int TranslationFloatBankOffset;

Texture Animation

Each texture specified in the string table has three Texture Animations associated with it. There are, in turn, three Keyframes within each Texture Animation:

Texture Animation
// 0x12/18 bytes long bytes long
/*0x00*/ Keyframe Scale;
/*0x06*/ Keyframe Rotation;
/*0x0C*/ Keyframe Translation;

Each Keyframe handles the scaling, rotation, or translation of the texture along the U, V, or W axes. Currently, it is unknown whether W is actually used or if it is a placeholder for the Z components present in the bone animation format, BCK.

In addition, it is likely that only one of these axes provides a rotation component for the whole texture.

Each Keyframe is stored like this:

Keyframe
// 6 bytes long
/*0x00*/ short ComponentCount; // Number of components in this keyframe
/*0x02*/ short FirstComponentOffset; // Offset of the first component
/*0x04*/ short UnknownShort; // ¯\_(ツ)_/¯

String Table and Texture Index Table

The string table and the texture index table work together to specify what texture in what material to operate on. The string table gives the name of the material, and the texture index table gives the index of the texture within that material.

In order to get the texture index for any given material, simply use the material's index when accessing the texture index table.

String Table

For information on the string table, see here.

Texture Index Table

The texture index table is simply an array of bytes, where each byte is the index of a texture. It is padded to the nearest 4 bytes.

There is one texture for each material in the string table.

Texture Center Table

There is one vector 3 (three floats to represent U, V, and W) for each texture that is manipulated in the animation. This vector represents the center point of the image.

Databanks

The databanks appear very similar to those used in the BCK format. Scaling and translation data use floats, while rotation data uses shorts (int16).

However, unlike the databanks used in BCK, the data stored does not appear to have a specific format - that is, there is no timestamp or tangent data. Each bank stores only the values used for animation.

BTP (Facial Animation/Texture Swap)


TPT1 Header

// 0x20/32 bytes long
/*0x00*/ char[4] Magic_TPT1;
/*0x04*/ int TPT1Size;
/*0x08*/ byte Flag; // Assuming from BCK/BTP
/*0x09*/ byte AngleMultiplier; // Assuming from BCK/BTP. Probably not used
/*0x0A*/ short AnimationLength; // Can be zero, probably because Facial Animation entries specify their own length
/*0x0C*/ short FacialAnimationEntryCount;
/*0x0E*/ short Unknown2;
/*0x10*/ int FacialAnimationEntriesOffset;
/*0x14*/ int TextureIndexBankOffset;
/*0x18*/ int RemapTableOffset; // Possibly? Not sure.
/*0x1C*/ int StringTableOffset;
Facial Animation

Each material specified in the string table has one Facial Animation entry. The entry is laid out like this:

// 8 bytes long
/*0x00*/ short FrameCount; // Number of frames in the anim
/*0x02*/ short FirstIndexOffset; // Index of the first texture index in the texture index bank
/*0x04*/ short Unknown1; // Always 0x00FF?
/*0x06*/ short Unknown2; // Always 0xFFFF?
Texture Index Bank

The texture index bank is a bank of shorts. It appears to specify what texture the material should use for every frame in the animation. Althought it is not confirmed, it is assumed that the indexes refer to the texture remap table used in the model's material data.

Remap Table (?)

A remap table is usually included right before a string table. Whether the data here is a remap table has yet to be confirmed.

String Table

For information on the string table, see here.

BRK (TEV Register Animation)


To-Do

BMT (Alternate Materials)


BMT files are simply a standard MAT3 chunk from the BMD/BDL model format with the standard header attached.