The goal of cast is to create an easy to use format for models, animations, materials, and game worlds. In addition, cast should be able to produce the same scenes in any 3d software.
Autodesk Maya (2012+): Releases
Blender (3.0+): Releases
.NET Framework (Reference): Libraries/DotNet
.NET Framework (by Scobalula): Cast.NET
Python: Libraries/Python
CastModelViewer (By echo000): Github
SECast, a lossless converter to cast: SECast
Note: If your tool supports exporting to cast directly, that is always better.
Frequently asked questions: FAQ
All files start with a cast header:
struct CastHeader{ uint32_t Magic; // char[4] cast (0x74736163)uint32_t Version; // 0x1uint32_t RootNodes; // Number of root nodes, which contain various sub nodes if necessaryuint32_t Flags; // Reserved for flags, or padding, whichever is needed};
A cast file is basically a group of generic nodes. Nodes are given a unique registered id, which can tell the loader what the data is, and how to handle it.
Following the cast header is a collection of nodes which must be of type CastId::Root.
A node looks like:
struct CastNodeHeader{ CastId Identifier; // Used to signify which class this node usesuint32_t NodeSize; // Size of all data and sub data following the nodeuint64_t NodeHash; // Unique hash, like an id, used to link nodes togetheruint32_t PropertyCount; // The count of propertiesuint32_t ChildCount; // The count of direct children nodes// We must read until the node size hits, and that means we are done.// The nodes are in a stack layout, so it's easy to load, FILO order.};
There are several registered cast ids available:
enum class CastId : uint32_t{ Root = 0x746F6F72, Model = 0x6C646F6D, Mesh = 0x6873656D, BlendShape = 0x68736C62, Skeleton = 0x6C656B73, Bone = 0x656E6F62, IKHandle = 0x64686B69, Constraint = 0x74736E63, Animation = 0x6D696E61, Curve = 0x76727563, CurveModeOverride = 0x564F4D43, NotificationTrack = 0x6669746E, Material = 0x6C74616D, File = 0x656C6966, Instance = 0x74736E69, Metadata = 0x6174656D, };
Following a node, is the list of properties [Node.PropertyCount], a property looks like:
struct CastPropertyHeader{ CastPropertyId Identifier; // The element type of this propertyuint16_t NameSize; // The size of the name of this propertyuint32_t ArrayLength; // The number of elements this property contains (1 for single)// Following is UTF-8 string lowercase, size of namesize, NOT null terminated// cast_property[ArrayLength] array of data};
For properties, cast has several built in types:
enum class CastPropertyId : uint16_t{ Byte = 'b', //Short = 'h', // Integer32 = 'i', // Integer64 = 'l', // Float = 'f', // Double = 'd', // String = 's', // Null terminated UTF-8 string Vector2 = 'v2', // Float precision vector XY Vector3 = 'v3', // Float precision vector XYZ Vector4 = 'v4'// Float precision vector XYZW};
To read a cast file, you just need to traverse the root nodes and their children. Properties always come before a nodes children. Each node has the total size of itself, and all children, so if a processor doesn't understand a node id, it can skip the entire node and continue reading.
Cast ids are stored as integers to make it faster to serialize and deserialize.
Field | Type(s) | IsArray | Required |
---|---|---|---|
Children | Skeleton, Mesh, Material | True | False |
Parent | Root | False | True |
Property (id) | Type(s) | IsArray | Required |
---|---|---|---|
Name (n) | String (s) | False | False |
Field | Type(s) | IsArray | Required |
---|---|---|---|
Children | None | True | False |
Parent | Model | False | True |
Property (id) | Type(s) | IsArray | Required |
---|---|---|---|
Name (n) | String (s) | False | False |
Vertex Position Buffer (vp) | Vector 3 (v3) | True | True |
Vertex Normal Buffer (vn) | Vector 3 (v3) | True | False |
Vertex Tangent Buffer (vt) | Vector 3 (v3) | True | False |
Vertex Color Buffer (c%d) | Integer 32 (i) | True | False |
Vertex UV Buffer (u%d) | Vector 2 (v2) | True | False |
Vertex Weight Bone Buffer (wb) | Integer 32 (i), Short (h), Byte (b) | True | False |
Vertex Weight Value Buffer (wv) | Float (f) | True | False |
Face Buffer (f) | Integer 32 (i), Short (h), Byte (b) | True | True |
Color Layer Count (cl) | Integer 32 (i), Short (h), Byte (b) | False | True if has color layers else False |
UV Layer Count (ul) | Integer 32 (i), Short (h), Byte (b) | False | True if has uv layers else False |
Maximum Weight Influence (mi) | Integer 32 (i), Short (h), Byte (b) | False | True if has weights else False |
Skinning Method (sm) | String (s) [linear, quaternion] | False | False |
Material (Hash of CastNode:Material) (m) | Integer 64 (l) | False | False |
Notes:
Face Buffer
is an index into the current meshes vertex data buffers where (0, 1, 2) are the first three vertices from this mesh.
The Face Buffer
follows CCW (right-handed) winding order, this may be different in other apis, where you may have to remap the indices.
If a face contains an invalid index combination (0, 1, 1), (0, 1, 0), (0, 0, 0)
where two or more indices are the same, it is acceptable for the user processing these faces to ignore them in order to properly render the mesh. It would be wise to present the user with a warning stating that this happened.
Each vertex descriptor buffer must contain the same number of elements ex: if you have 16 vertices, you must have 16 normals if they exist, 16 colors if the buffer exists. Otherwise it's assumed they are default / skipped.
Weights are additive which means having the same bone with 0.5
and 0.5
would end up making that bones influence 1.0
for example.
The default skinning method is linear
. When set to quaternion
dual quaternion skinning is used.
NEW 8/18/2024: The vertex color specification has changed, in order to support multiple color layers, a new Color Layer Count (cl)
was added which mimics the UV Layer Count (ul)
property.
To be backwards compatible, cast processors should check for cl
, and use that by default along with the new c%d
layer properties.
If the cl
property does not exist, a processor should check for the legacy vc
property which is the one and only color layer if it exists.
Field | Type(s) | IsArray | Required |
---|---|---|---|
Children | None | True | False |
Parent | Model | False | True |
Property (id) | Type(s) | IsArray | Required |
---|---|---|---|
Name (n) | String (s) | False | True |
Base Shape (Hash of CastNode:Mesh) (b) | Integer 64 (l) | False | True |
Target Shape Vertex Indices (vi) | Byte (b), Short (h), Integer 32 (i) | True | True |
Target Shape Vertex Positions (vp) | Vector 3 (v3) | True | True |
Target Weight Scale (ts) | Float (f) | True | False |
Notes:
The Base Shape
must be an existing cast mesh.
The Target Shape Vertex Indices
and Target Shape Vertex Positions
must be the same length as they are paired together.
Target Shape Vertex Positions
is the final value of each changed vertex position ignoring the Base Shape
's corresponding vertex.
Target Weight Scale
indicates the maximum value the target shape can deform to and should default to 1.0
.
Field | Type(s) | IsArray | Required |
---|---|---|---|
Children | Bone, IKHandle, Constraint | True | False |
Parent | Model | False | True |
Field | Type(s) | IsArray | Required |
---|---|---|---|
Children | None | True | False |
Parent | Skeleton | False | True |
Property (id) | Type(s) | IsArray | Required |
---|---|---|---|
Name (n) | String (s) | False | True |
Parent Index (p) | Integer 32 (i) | False | False |
Segment Scale Compensate (ssc) | Byte (b) [True, False] | False | False |
Local Position (lp) | Vector 3 (v3) | False | False |
Local Rotation (lr) | Vector 4 (v4) | False | False |
World Position (wp) | Vector 3 (v3) | False | False |
World Rotation (wr) | Vector 4 (v4) | False | False |
Scale (s) | Vector 3 (v3) | False | False |
Notes:
Segment Scale Compensate
should default to True
when not specified.
Scale
is always local to the current bone.
Field | Type(s) | IsArray | Required |
---|---|---|---|
Children | None | True | False |
Parent | Skeleton | False | True |
Property (id) | Type(s) | IsArray | Required |
---|---|---|---|
Name (n) | String (s) | False | False |
Start Bone Hash (sb) | Integer 64 (l) | False | True |
End Bone Hash (eb) | Integer 64 (l) | False | True |
Target Bone Hash (tb) | Integer 64 (l) | False | False |
Pole Vector Bone Hash (pv) | Integer 64 (l) | False | False |
Pole Bone Hash (pb) | Integer 64 (l) | False | False |
Use Target Rotation (tr) | Byte (b) [True, False] | False | False |
Notes:
Use Target Rotation
should default to False
when not specified.
Pole Bone
must only effect the twist of the chain, in general you either have a Pole Bone
or a Pole Vector Bone
.
Field | Type(s) | IsArray | Required |
---|---|---|---|
Children | None | True | False |
Parent | Skeleton | False | True |
Property (id) | Type(s) | IsArray | Required |
---|---|---|---|
Name (n) | String (s) | False | False |
Constraint Type (ct) | String (s) [pt, or, sc] | False | True |
Constraint Bone Hash (cb) | Integer 64 (l) | False | True |
Target Bone Hash (tb) | Integer 64 (l) | False | True |
Maintain Offset (mo) | Byte (b) [True, False] | False | False |
Skip X (sx) | Byte (b) [True, False] | False | False |
Skip Y (sy) | Byte (b) [True, False] | False | False |
Skip Z (sz) | Byte (b) [True, False] | False | False |
Notes:
The constraint type values correspond to:
pt
Point Constraint, which applies to translations.
or
Orient Constraint, which applies to rotations.
sc
Scale Constraint, which applies to scales.
Maintain offset should default to False
when not specified.
Skip X, Skip Y, and Skip Z should default to False
when not specified and refer to ignoring that axis in the constraint.
Field | Type(s) | IsArray | Required |
---|---|---|---|
Children | File | True | False |
Parent | Model | False | True |
Property (id) | Type(s) | IsArray | Required |
---|---|---|---|
Name (n) | String (s) | False | True |
Type (t) | String (s) | False | True |
Albedo File Hash (albedo) | Integer 64 (l) | False | False |
Diffuse File Hash (diffuse) | Integer 64 (l) | False | False |
Normal File Hash (normal) | Integer 64 (l) | False | False |
Specular File Hash (specular) | Integer 64 (l) | False | False |
Emissive File Hash (emissive) | Integer 64 (l) | False | False |
Gloss File Hash (gloss) | Integer 64 (l) | False | False |
Roughness File Hash (roughness) | Integer 64 (l) | False | False |
Ambient Occlusion File Hash (ao) | Integer 64 (l) | False | False |
Cavity File Hash (cavity) | Integer 64 (l) | False | False |
Anisotropy File Hash (aniso) | Integer 64 (l) | False | False |
Extra (x) File Hash (extra%d) | Integer 64 (l) | False | False |
Field | Type(s) | IsArray | Required |
---|---|---|---|
Children | None | True | False |
Parent | CastNode | False | True |
Property (id) | Type(s) | IsArray | Required |
---|---|---|---|
Path (p) | String (s) | False | True |
Field | Type(s) | IsArray | Required |
---|---|---|---|
Children | Skeleton, Curve, CurveModeOverride, NotificiationTrack | True | True |
Parent | Root | False | True |
Property (id) | Type(s) | IsArray | Required |
---|---|---|---|
Name (n) | String (s) | False | False |
Framerate (fr) | Float (f) | False | True |
Looping (lo) | Byte (b) [True, False] | False | False |
Field | Type(s) | IsArray | Required |
---|---|---|---|
Children | None | True | False |
Parent | Animation | False | True |
Property (id) | Type(s) | IsArray | Required |
---|---|---|---|
Node Name (nn) | String (s) | False | True |
Key Property Name (kp) | String (s) [rq, tx, ty, tz, sx, sy, sz, bs, vb] | False | True |
Key Frame Buffer (kb) | Byte (b), Short (h), Integer 32 (i) | True | True |
Key Value Buffer (kv) | Byte (b), Short (h), Integer 32 (i), Float (f), Vector 4 (v4) | True | True |
Mode (m) | String (s) [additive, absolute, relative] | False | True |
Additive Blend Weight (ab) | Float (f) | False | False |
Notes:
All curve keyframes are in object/node space.
The Mode
determines how each curve keyframe is applied to the node.
additive
: The keyframe is added to the current scene frame value of the nodes property.
absolute
: The keyframe is the exact value for the given frame.
relative
: The keyframe is added to the rest position value of the nodes property.
The property values correspond to:
=0
= hidden.
>=1
= visible.
rq
Rotation Quaternion and expects v4
values.
tx
Translation 'X' and expects f
values.
ty
Translation 'Y' and expects f
values.
tz
Translation 'Z' and expects f
values.
sx
Scale 'X' and expects f
values.
sy
Scale 'Y' and expects f
values.
sz
Scale 'Z' and expects f
values.
bs
BlendShape Weight and expects f
values.
vb
Visibility and expects b
, h
, or i
values.
The properties tx
, ty
, tz
, sx
, sy
, sz
, bs
, vb
should interpolate linearly.
The property rq
should interpolate with quaternion slerp.
Field | Type(s) | IsArray | Required |
---|---|---|---|
Children | None | True | False |
Parent | Animation | False | True |
Property (id) | Type(s) | IsArray | Required |
---|---|---|---|
Node Name (nn) | String (s) | False | True |
Mode (m) | String (s) [additive, absolute, relative] | False | True |
Override Translation Curves (ot) | Byte (b) [True, False] | False | False |
Override Rotation Curves (or) | Byte (b) [True, False] | False | False |
Override Scale Curves (os) | Byte (b) [True, False] | False | False |
Notes:
See Curve
notes above for the definition of each Mode
value.
Override Translation Curves
should default to False
when not specified.
Override Rotation Curves
should default to False
when not specified.
Override Scale Curves
should default to False
when not specified.
The override node and all of it's children should override their curves mode to the new mode.
The override node must be present at the time of processing in order to determine if a child bone is a descendent.
Field | Type(s) | IsArray | Required |
---|---|---|---|
Children | None | True | False |
Parent | Animation | False | True |
Property (id) | Type(s) | IsArray | Required |
---|---|---|---|
Name (n) | String (s) | False | True |
Key Frame Buffer (kb) | Byte (b), Short (h), Integer 32 (i) | True | True |
Field | Type(s) | IsArray | Required |
---|---|---|---|
Children | File | True | False |
Parent | Root | False | True |
Property (id) | Type(s) | IsArray | Required |
---|---|---|---|
Name (n) | String (s) | False | False |
Reference File (Hash of CastNode:File) (rf) | Integer 64 (l) | False | True |
Position (p) | Vector 3 (v3) | False | True |
Rotation (r) | Vector 4 (v4) | False | True |
Scale (s) | Vector 3 (v3) | False | True |
Field | Type(s) | IsArray | Required |
---|---|---|---|
Children | None | True | False |
Parent | Root | False | True |
Property (id) | Type(s) | IsArray | Required |
---|---|---|---|
Author (a) | String (s) | False | False |
Software (s) | String (s) | False | False |
Up Axis (up) | String (s) [x, y, z] | False | False |
Notes:
Author
and Software
are just for tagging cast files and have no use outside of metadata.
Up Axis
can be used as a hint to software to adjust the scene to match a specific up axis.
A cast file can have any number of meta nodes but properties designed for hinting should only use the first metadata node instance.
Format designed by DTZxPorter with input from the community.
Icons by Smashicons