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.
- Python: Libraries/Python
- .NET Framework (by Scobalula): Cast.NET
- 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 are in little endian byte order and start with a cast header:
struct CastHeader
{
uint32_t Magic; // char[4] cast (0x74736163)
uint32_t Version; // 0x1
uint32_t RootNodes; // Number of root nodes, which contain various sub nodes if necessary
uint32_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 uses
uint32_t NodeSize; // Size of all data and sub data following the node
uint64_t NodeHash; // Unique hash, like an id, used to link nodes together
uint32_t PropertyCount; // The count of properties
uint32_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,
Hair = 0x72696168,
BlendShape = 0x68736C62,
Skeleton = 0x6C656B73,
Bone = 0x656E6F62,
IKHandle = 0x64686B69,
Constraint = 0x74736E63,
Animation = 0x6D696E61,
Curve = 0x76727563,
CurveModeOverride = 0x564F4D43,
NotificationTrack = 0x6669746E,
Material = 0x6C74616D,
File = 0x656C6966,
Color = 0x726C6F63,
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 property
uint16_t NameSize; // The size of the name of this property
uint32_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', // <uint8_t>
Short = 'h', // <uint16_t>
Integer32 = 'i', // <uint32_t>
Integer64 = 'l', // <uint64_t>
Float = 'f', // <float>
Double = 'd', // <double>
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) |
|---|---|
| Children | Model, Animation, Instance, Metadata |
| Parent | N/A |
Notes:
- A root node represents a scene in a cast file.
- A root node may have
0-nof any of it's children nodes. - All of a root nodes children must have unique hashes.
| Field | Type(s) |
|---|---|
| Children | Skeleton, Mesh, Hair, Blend Shape, Material |
| Parent | Root |
| Property (id) | Type(s) | IsArray | Required |
|---|---|---|---|
| Name (n) | String (s) | False | False |
| Position (p) | Vector 3 (v3) | False | False |
| Rotation (r) | Vector 4 (v4) | False | False |
| Scale (s) | Vector 3 (v3) | False | False |
Notes:
- A model may have at most one skeleton node.
- A model may have
0-nof the other children nodes. - The
Position,Rotation, andScaleproperties modify the model and it's children in world space.- Instance nodes should be preferred for large scene building.
| Field | Type(s) |
|---|---|
| Children | N/A |
| Parent | Model |
| 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), Vector 4 (v4) | 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 Bufferis an index into the current meshes vertex data buffers where (0, 1, 2) are the first three vertices from this mesh.- The
Face Bufferfollows 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.5and0.5would end up making that bones influence1.0for example. - The default skinning method is
linear. When set toquaterniondual 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 theUV Layer Count (ul)property.- To be backwards compatible, cast processors should check for
cl, and use that by default along with the newc%dlayer properties. - If the
clproperty does not exist, a processor should check for the legacyvcproperty which is the one and only color layer if it exists.
- To be backwards compatible, cast processors should check for
- NEW 4/21/2025: The vertex color buffer specification now allows supplying unpacked floating point rgba colors.
| Field | Type(s) |
|---|---|
| Children | N/A |
| Parent | Model |
| Property (id) | Type(s) | IsArray | Required |
|---|---|---|---|
| Name (n) | String (s) | False | False |
| Segments Buffer (se) | Integer 32 (i), Short (h), Byte (b) | True | True |
| Particle Buffer (pt) | Vector 3 (v3) | True | True |
| Material (Hash of CastNode:Material) (m) | Integer 64 (l) | False | False |
Notes:
- The
Particle Bufferstores the particles in order by each strand, in world space. - For each strand, there is a count in
Segments Buffer, there iscount + 1particles for each strand.- A segment is the connection between two particles.
- The sequence
1 -> 2 -> 3is two segments1 -> 2, 2 -> 3.
| Field | Type(s) |
|---|---|
| Children | N/A |
| Parent | Model |
| 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 Shapemust be an existing cast mesh. - The
Target Shape Vertex IndicesandTarget Shape Vertex Positionsmust be the same length as they are paired together. Target Shape Vertex Positionsis the final value of each changed vertex position ignoring theBase Shape's corresponding vertex.Target Weight Scaleindicates the maximum value the target shape can deform to and should default to1.0.
| Field | Type(s) |
|---|---|
| Children | Bone, IKHandle, Constraint |
| Parent | Model |
| Field | Type(s) |
|---|---|
| Children | N/A |
| Parent | Skeleton |
| 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 Compensateshould default toTruewhen not specified.Scaleis always local to the current bone.
| Field | Type(s) |
|---|---|
| Children | N/A |
| Parent | Skeleton |
| 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 Rotationshould default toFalsewhen not specified.Pole Bonemust only effect the twist of the chain, in general you either have aPole Boneor aPole Vector Bone.
| Field | Type(s) |
|---|---|
| Children | N/A |
| Parent | Skeleton |
| 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 |
| Custom Offset (co) | Vector 3 (v3), Vector 4 (v4) | False | False |
| Weight (wt) | Float (f) | 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:
ptPoint Constraint, which applies to translations.orOrient Constraint, which applies to rotations.scScale Constraint, which applies to scales.
- Maintain offset should default to
Falsewhen not specified. - Custom offset should match the following for the constraint types:
pt: Vector 3, default:[0.0, 0.0, 0.0].or: Vector 4, default:[0.0, 0.0, 0.0, 1.0].sc: Vector 3, default:[1.0, 1.0, 1.0].
- Skip X, Skip Y, and Skip Z should default to
Falsewhen not specified and refer to ignoring that axis in the constraint.
| Field | Type(s) |
|---|---|
| Children | File, Color |
| Parent | Model |
| Property (id) | Type(s) | IsArray | Required |
|---|---|---|---|
| Name (n) | String (s) | False | True |
| Type (t) | String (s) [pbr] | False | True |
| Albedo Hash (albedo) | Integer 64 (l) | False | False |
| Diffuse Hash (diffuse) | Integer 64 (l) | False | False |
| Normal Hash (normal) | Integer 64 (l) | False | False |
| Specular Hash (specular) | Integer 64 (l) | False | False |
| Gloss Hash (gloss) | Integer 64 (l) | False | False |
| Roughness Hash (roughness) | Integer 64 (l) | False | False |
| Emissive Hash (emissive) | Integer 64 (l) | False | False |
| Emissive Mask Hash (emask) | Integer 64 (l) | False | False |
| Ambient Occlusion Hash (ao) | Integer 64 (l) | False | False |
| Cavity Hash (cavity) | Integer 64 (l) | False | False |
| Anisotropy Hash (aniso) | Integer 64 (l) | False | False |
| Extra (x) Hash (extra%d) | Integer 64 (l) | False | False |
Notes:
- The hash properties link to children of the material which can be:
- A
Filewhich points to a texture. - A
Colorwhich has a single rgba value.
- A
| Field | Type(s) |
|---|---|
| Children | N/A |
| Parent | Material, Instance |
| Property (id) | Type(s) | IsArray | Required |
|---|---|---|---|
| Path (p) | String (s) | False | True |
| Field | Type(s) |
|---|---|
| Children | N/A |
| Parent | Material |
| Property (id) | Type(s) | IsArray | Required |
|---|---|---|---|
| Name (n) | String (s) | False | False |
| Color Space (cs) | String (s) [srgb, linear] | False | False |
| Rgba Color (rgba) | Vector 4 (v4) | False | True |
Notes:
- The
Color Spaceproperty should default tosrgbwhen not specified.
| Field | Type(s) |
|---|---|
| Children | Skeleton, Curve, CurveModeOverride, NotificationTrack |
| Parent | Root |
| 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) |
|---|---|
| Children | N/A |
| Parent | Animation |
| 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
Modedetermines 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:
rqRotation Quaternion and expectsv4values.txTranslation 'X' and expectsfvalues.tyTranslation 'Y' and expectsfvalues.tzTranslation 'Z' and expectsfvalues.sxScale 'X' and expectsfvalues.syScale 'Y' and expectsfvalues.szScale 'Z' and expectsfvalues.bsBlendShape Weight and expectsfvalues.vbVisibility and expectsb,h, orivalues.=0= hidden.>=1= visible.
- The properties
tx,ty,tz,sx,sy,sz,bs,vbshould interpolate linearly. - The property
rqshould interpolate with quaternion slerp.
| Field | Type(s) |
|---|---|
| Children | N/A |
| Parent | Animation |
| 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
Curvenotes above for the definition of eachModevalue. Override Translation Curvesshould default toFalsewhen not specified.Override Rotation Curvesshould default toFalsewhen not specified.Override Scale Curvesshould default toFalsewhen 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) |
|---|---|
| Children | N/A |
| Parent | Animation |
| 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) |
|---|---|
| Children | File |
| Parent | Root |
| 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) |
|---|---|
| Children | N/A |
| Parent | Root |
| 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 |
| Scene Root (sr) | String (s) | False | False |
Notes:
AuthorandSoftwareare just for tagging cast files and have no use outside of metadata.Up Axiscan be used as a hint to software to adjust the scene to match a specific up axis.Scene Rootcan be used as a root directory for resolving instance and other path relative nodes.- 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