SMD
The SMD file format (short for StudioModel Data) stores 3D models in ASCII for analysis and compilation by studiomdl. SMD files are usually generated by an SMD export plug-in for a given model editor package like MilkShape.
Software
Aside from Source and GoldSrc, SMD is known to be used by Sauerbraten and third party tools for The Sims and Mount & Blade. It is also optionally used by the FTE IQM Tool, used to create skeletal IQM models used by various id Tech 2 and id Tech 3 source ports.
General notes
- X is north in SMD. Elsewhere in Source it is east.
- The format is carriage return sensitive: text editors should use
CR
(Mac) orCRLF
(Windows) line terminators instead of justLF
(Linux). Each command must be on a separate line. There should also be a single blank line at the end (and only the end) of the file. - White space is the only delimiter: any combination of tabs and spaces can be used to separate values, and for this reason multiword names should be enclosed in "quotation marks". Bug:Avoid using tab. Its presence can crash studiomdl in very large SMDs.
- Comments are not supported by GoldSrc studiomdl.
For Source studiomdl, the following comment delimiters can be used (but may be stripped by 3D modeling programs):- Stand-alone line comments start with // (double forward slash)
- End-line comments start with # (hashtag) or ; (semicolon)
Types
- Reference / Collision
- A complete snapshot of the model, including one frame of animation to define the default pose. Collision meshes follow the same pattern.
header
nodes
skeleton
triangles
- Animation
- A single skeletal animation.
header
nodes
skeleton
- Vertex (only in )
- A flex animation library. Usually has extension
.vta
. header
nodes
skeleton
(a "time <n>" header for each flex shape; no position data required)vertexanimation
Data blocks
Here are the components of an SMD file, considered in order:
Header
Simply:
version 1
Nodes
A list of all the bones in the model.
Syntax
nodes
- Starts the node block.
<int|ID> "<string|Bone Name>" <int|Parent ID>
- A bone definition. Unique ID number (does not have to be sequential), name in quote marks and the parent bone's ID. Bones without parents (i.e. children of the world) have a Parent ID of
-1
.Note:Studiomdl matches bones across SMDs by name. IDs are internal to each file. end
- Ends the data block.
Example
A root bone with one child:
nodes 0 "root" -1 1 "child" 0 end
Skeleton
Position data for each bone in each animation frame. In a reference SMD there is only one frame, which contains the model's default posture.
Syntax
skeleton
- Begins the skeleton block.
time <int>
- Begins a new frame. Any range of numbers can be used, so long as they increase sequentially.
<int|bone ID> <float|PosX PosY PosZ> <float|RotX RotY RotZ>
- A bone's position relative to its parent (give absolute values in the case of root bones).
Pos
is position in units relative to the parent bone.Rot
is local Tait-Bryan angles, given in radians. (90° = 1.570796 rad)
- Tip:The first frame must include all bones. After that, those which have not moved relative to their parent since the last frame can be omitted.
- Tip:Converting from a local rotation matrix to Euler angles might require you to invert the rotation matrix before conversion.
end
- Ends the data block.
Example
Bone 1 move two units along the Y axis, then back again:
skeleton time 0 0 0 0 0 1.570796 0 0 1 1 0 0 0 0 0 time 1 1 1 2 0 0 0 0 time 2 1 1 0 0 0 0 0 end
Triangles
A triangle in a model is defined by three vertices. Included in each triangle is its UV co-ordinates and envelope weights.
Syntax
triangles
- Begins the triangle block.
<material () or texture ()>
- Defines the start of a new triangle and the material to apply to it.
- File extensions (anything after a ".") are ignored in Source, but must be be
bmp
in GoldSrc. - Do not enclose in quotes and do not include a path ($cdmaterials () or $cdtexture () will provide one).
<int|Parent bone> <float|PosX PosY PosZ> <normal|NormX NormY NormZ> <float|U V> <int|links> <int|Bone ID> <float|Weight> [...]
- Defines a vertex.
Pos
is in world unitsNorm
is the vertex normal, dictating how sharp or smooth the geometry is shaded- U and V are the vertex's UV map co-ordinates
- The final three values are optional: they override
<Parent bone>
to define a series of weightmap links.Bone ID
andWeight
are repeated for each link. If the weights do not add up to 1, any remaining value is placed on<Parent bone>
. - Note:For SMDs included with $lod, Studiomdl can determine a vertex's weight links by copying those of the closest reference mesh vertex.
end
- Ends triangle block.
Example
A flat, two-sided square. The left edge envelopes bone 0 and the right edge envelopes bone 1, and the UV map is a simple square projection:
triangles my_material.bmp 0 0 0 0 0 0 1 0 1 1 0 1 0 0 -1 0 0 0 1 0 0 1 0 1 1 1 -1 0 0 0 1 1 0 1 1 1 my_material.bmp 0 0 0 0 1 0 1 0 1 1 0 1 1 1 -1 0 1 0 1 1 0 1 1 1 1 1 0 0 1 0 1 1 1 1 1 1 my_material.bmp 1 1 -1 0 0 0 1 1 0 1 1 1 0 0 -1 0 0 0 1 0 0 1 0 1 0 0 0 0 0 0 1 0 1 1 0 1 my_material.bmp 1 1 0 0 1 0 1 1 1 1 1 1 1 1 -1 0 1 0 1 1 0 1 1 1 0 0 0 0 1 0 1 0 1 1 0 1 end
Vertexanimation
(only in Source) Position of vertices in various morph targets, for use in vertex animation or flex animation. While this block uses the same time
keyword as skeleton
, each 'frame' is instead a discrete, static shape. Transitions between them are created on-demand by the engine.
nodes
and a skeleton
block are needed in each VTA. The skeleton block needs only contain a "time <n>" header for each flex shape.Syntax
vertexanimation
- Begins the vertex animation block.
time <int>
- Begins a morph target. The first target must include all vertices on the mesh in their reference positions; subsequent targets should include only vertices that differ from the reference.
<int|ID> <float|PosX PosY PosZ> <normal|NormX NormY NormZ>
- A vertex.
end
- Ends the data block.