You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Cast | A new open-source container for models, animations, and materials
The goal of cast is to create an engine agnostic format that can be parsed and written with ease. In addition, cast should have very similar output on any engine.
structCastHeader
{
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:
structCastNodeHeader
{
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.
};
Following a node, is the list of properties [Node.PropertyCount], a property looks like:
structCastPropertyHeader
{
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
};
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 integers for performance, unlike FBX where nodes are full strings.
Cast processors:
Model:
Field
Type(s)
IsArray
Required
Children
Skeleton, Mesh, Material
True
False
Parent
Root
False
True
Mesh:
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 (vc)
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
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
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.
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.
Blend Shape:
Field
Type(s)
IsArray
Required
Children
None
True
False
Parent
Model
False
True
Property (id)
Type(s)
IsArray
Required
Base Shape (Hash of CastNode:Mesh) (b)
Integer 64 (l)
False
True
Target Shapes (Hashes of CastNode:Mesh) (t)
Integer 64 (l)
True
True
Target Weight Scales (ts)
Float (f)
True
False
Notes:
At a minimum one Base Shape and one Target Shape must be present.
Target Weight Scales indicates the maximum value the target shape can deform to. The count usually will match Target Shape(s) but if it does not plugins should fall back to 1.0 as the default.