SMD file format: Difference between revisions

From Valve Developer Community
Jump to navigation Jump to search
(various improvements)
Line 1: Line 1:
The '''SMD''' ('''S'''tudio '''M'''odel '''D'''ata) file format stores 3D geometry data in ASCII, for analysis and compilation by [[studiomdl]]. SMD files are usually generated by the [[SMD export]]er plug-in for a given [[model editor]] package.
The '''StudioMDL Data''' file format stores 3D geometry data in ASCII for analysis and compilation by [[studiomdl]]. SMD files are usually generated by an [[SMD export]]er plug-in for a given [[model editor]] package.


The format is carriage return sensitive &mdash; each line must end with a carriage return. The file should also include at least one carriage return after the final end statement. 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 (<code>"</code>).
The format is carriage return sensitive: 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.


==Types of SMD==
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". There is no support for comments.
SMD files come in two flavors, Reference and Animation files. Although one file can contain both.


The '''Reference SMD''' file is a complete snapshot of the model, including its geometry, its skeletal structure, one animation frame to describe the position of the skeletal bones, its texture, and the links between its mesh vertices and its skeleton. Reference SMDs do not contain any animation data &mdash; they produce only a static image of the complete model at one point in time.
== Types ==
<!-- what about "Physbox SMD" ? another type of "Reference SMD" ?-->


The '''Animation SMD''' omits the triangle and texture map data and contains only animation and skeletal data.
;Reference
:''A complete snapshot of the model, including one frame of animation to define the default pose. Also used for [[collision mesh]]es.''
:<code>[[#Header|header]]</code>
:<code>[[#Nodes|nodes]]</code>
:<code>[[#Skeleton|skeleton]]</code>
:<code>[[#Triangles|triangles]]</code>
; Animation
: ''A single skeletal animation.''
:<code>[[#Header|header]]</code>
:<code>[[#Nodes|nodes]]</code>
:<code>[[#Skeleton|skeleton]]</code>
; Vertex
: ''For [[flex animation]]. Usually has extension <code>.vta</code>. Precise structure unclear.''
:<code>[[#Header|header]]</code>
:<code>[[#Nodes|nodes]]</code>
:<code>[[#Skeleton|skeleton]]</code>
:<code>[[#Vertexanimation|vertexanimation]]</code>


In addition, [[VTA]] files (facial animation) use a similar format to SMD, but contain only vertex animation data.
== Data blocks ==


==SMD file sections==
Here are the components of an SMD file, considered in order:
Here are the sections of an SMD file, considered in order:


===Header data===
{{tip|Unless otherwise noted all [[integer]] values begin at 0 and all [[floating point]] values are limited to six decimal places.}}
The only header data required is the tag <code>version 1</code> in the first line of the file. This is compatible with both [[Half-Life]] and [[Half-Life 2]].


===Node tree data===
=== Header ===
Builds a list of all the bones in the skeleton. Each bone has a unique ID number, a unique text name and a pointer to the ID number of its parent. Children of the world use <code>–1</code> as their parent ID. ID numbers are integers (starting from 0). Names are text, enclosed in quotes. Names may contain spaces.


*<code>nodes</code>
Simply:
:Starts the node tree data block.
*<code>''<ID>'' "''Bone Name''" ''<parent ID>''</code>
:<code>''<ID>''</code> is a the ID number for this bone. <code>"''Bone Name''"</code> is a text name for the bone, enclosed in quotes. <code>''<parent ID>''</code> is the ID number of the bone’s parent. Children of the world (unparented objects) have a parent ID of <code>-1</code>.
*<code>end</code>
:Ends the node tree data block.


===Skeleton Pose data===
version 1
This block contains the position and rotation data for bones in the skeleton. In an animation SMD there will be a "time" block for every frame in the animation. In reference SMDs there will only be one time block.


The skeleton block is begun by the <code>skeleton</code> tag and ended by an <code>end</code> tag. A time block begins with <code>time ''<frame>''</code> and end when a new "time" tag is encountered.
=== Nodes ===


Each frame is defined by a line telling the frame number, e.g. <code>time 0</code>, followed by the bone's new position and rotations. The frame will end when a new one is defined or the end of the skeleton tree is reached. The frames doesn't have to start at 0 (it can also be negative), but they have to increase in numbers. Frames may be skipped, they will then be linearly interpolated instead. A frame can exclude data for a bone. {{todo|Does excluded bone data copy the previous data, interpolate between the nearest frames, or something else?}}
A list of all the bones in the model.


*<code>Skeleton</code>
{{note|Bones without attached vertices will not be compiled.}}
:Begins the skeleton pose block.
*<code>Time 0</code>
:Begins this time block
*<code>''<ID>'' ''<PosX>'' ''<PosY>'' ''<PosZ>'' ''<RotX>'' ''<RotY>'' ''<RotZ>''</code>
:<code>''<ID>''</code> is the bone ID. <code>''<PosX>'' ''<PosY>'' ''<PosZ>''</code> is the position in world units (good to 6 significant digits). <code>''<RotX>'' ''<RotY>'' ''<RotZ>''</code> are local [http://en.wikipedia.org/wiki/Euler_angles Euler] rotations in [http://en.wikipedia.org/wiki/Radian radians]. Bones which are not children of the world report their position and rotations in their parent's local space.
*<code>Time 1</code>
:Begins the next time block. Any bone without changes from the last frame doesn't have to be entered, but will be linearly interpolated if a new position is later defined.
*<code>end</code>
:Ends skeleton pose block.


===Triangle block===
A root bone with one child:
The triangle block contains a list of triangles. Each triangle is preceded by a texture file name (filename only &mdash; path data is supplied in the QC file as <code>$cdmaterials</code>). Each vertex of the triangle then reports its parent bone’s ID (Bone with the highest <!--is it the word highest?--> weights value), the vertex's position, the vertex's texture coordinates, its normals, and bone weights (bone weights can be omitted per vertex).


The Triangle block is begun with the <code>triangles</code> tag and ends with the <code>end</code> tag.
nodes
0 "root" -1
1 "child" 0
end


*<code>Triangles</code>
; <code>nodes</code>
:Begins the triangle block
: Starts the node block.
*<code>''texturename''.*</code>
; <code><[[int]]|ID> "<[[string]]|Bone Name>" <int|Parent ID></code>
:Name of the texture file for the texture assigned to this face, including the file suffix like <code>.tga</code>. Do not enclose in quotes.
: 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 <code>-1</code>.
*<code>''<Parent>'' ''<PosX>'' ''<PosY>'' ''<PosZ>'' ''<NormX>'' ''<NormY>'' ''<NormZ>'' ''<TexU>'' ''<TexV>'' ''<# of links>'' ''<bone ID>'' ''<weight>'' ''[...]''</code>
; <code>end</code>
:<code>''<Parent>''</code> is the ID number of the vertex's parent bone. <code>''<PosX>'' ''<PosY>'' ''<PosZ>''</code> is the position of the vertex in world space. <code>''<NormX>'' ''<NormY>'' ''<NormZ>''</code> are the components of the vertex's normal vector (used for smoothing the suface). <code>''<TexU>''</code> and <code>''<TexV>''</code> are the texture coordinates for this vertex.
: Ends the data block.
:<code>''<bone ID>'' ''<weight>''</code> will be looped at the end of each vertex ''<# of links>'' times.
:If the weights don't add up to 1.0 the rest will be assigned to the ''<Parent>'' bone. Same if no ''<# of links>'' is defined or if it is 0.
:Each triangle contains 3 vertex records.
*<code>''nextTextureName''.tga</code>
:new texture file begins a new triangle listing
*<code>end</code>
:ends triangle block.


===Vertex Animation Files===
=== Skeleton ===
VTA files contain the position and normal data for every vertex in the model. There will be a "time" block for every frame in the vertex animation.


The vertex animation is begun by the <code>vertexanimation</code> tag and ended by an <code>end</code> tag. Time block begin with <code>time ''<frame>''</code> and end when a new "time" tag is encountered or the end of the vertex animation block is reached.
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.


*<code>vertexanimation</code>
{{note|There can only be one animation in each SMD.}}
:Begins the vertex animation block
*<code>Time 0</code>
:Begins this time block. Time 0 serves as vertex index, so it should have all vertices of the model giving a index number for each.
*<code>''<ID>'' ''<PosX>'' ''<PosY>'' ''<PosZ>'' ''<NormX>'' ''<NormY>'' ''<NormZ>''</code>
:<code>''<ID>''</code> is the vertex ID. <code>''<PosX>'' ''<PosY>'' ''<PosZ>''</code> is the position in world units (good to 6 significant digits). <code>''<NormX>'' ''<NormY>'' ''<NormZ>''</code> are the components of the vertex's normal vector


*<code>Time 1</code>
This code makes bone 1 move two units along the Y axis, then back again:
:Begins next time block.
 
*<code>end</code>
skeleton
:Ends vertex animation block
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
 
; <code>skeleton</code>
: Begins the skeleton block.
; <code>time <[[int]]></code>
: Begins a new frame. Any range of numbers can be used, so long as they increase sequentially.
; <code> <int|bone ID> <[[float]]|PosX PosY PosZ>  <float|RotX RotY RotZ> </code>
: A bone's position relative to its parent (give absolute values in the case of root bones).
:* <code>Pos</code> is position in [[unit]]s.
:* <code>Rot</code> is local [[Wikipedia:Euler angles|Euler angles]], given in [[Wikipedia:Radian|radians]]. (90&deg; = 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.}}
; <code>end</code>
: Ends the data block.
 
=== Triangles ===
All of the polygons in the model by their three [[vertex|vertices]]. Included in each polygon is its [[UV]] co-ordinates and [[envelope]] weights.
 
{{note|Source's polygons are one-sided. The active face is the one around which the vertices can be traced clockwise.}}
 
This code represents 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
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
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
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
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
 
; <code>triangles</code>
: Begins the triangle block.
; <code><material></code>
: Defines the start of a new triangle and the material to apply to it. Anything after a '.' (e.g. a file extension) is ignored. Do not enclose in quotes and do not include a path ([[$cdmaterials]] will provide one).
; <code><[[int]]|Parent bone> <[[float]]|PosX PosY PosZ> <[[normal]]|NormX NormY NormZ> <normal|U V> <int|links> <int|Bone ID> <normal|Weight> [...]</code>
: Defines a [[vertex]]. <code>Pos</code> is in world [[unit]]s. <code>Norm</code> is used to smooth the surface of the model ({{todo|How?}}). U and V are the vertex's [[UV map]] co-ordinates.
: The final three options are optional: they override <code><Parent bone></code> to define a series of weighted envelopes. <code>Bone ID</code> and <code>Weight</code> are repeated for each link. If the weights do not add up to 1, any remaining value is placed on <code><Parent bone></code>.
; <code>end</code>
: Ends triangle block.
 
=== Vertexanimation ===
 
Position of vertices in various morph targets (for [[flex animation]]). Although this block uses the same <code>time</code> keyword as <code>[[#Skeleton|skeleton]]</code>, each 'frame' is a discrete shape: transitions between them are created on-demand by the engine.
 
{{warning|The precise structure of this block is unclear. It is known that a skeleton block is required elsewhere in the file, though all frames in it appear to be the same!}}
 
; <code>vertexanimation</code>
: Begins the vertex animation block.
;<code>time <[[int]]></code>
: Begins a morph target. It is unclear how many or even which vertices should be included (though it's a safe bet that the modified ones are among them).
; <code><int|ID> <[[float]]|PosX PosY PosZ> <[[normal]]|NormX NormY NormZ></code>
: A vertex. Its ID is defined by its position in <code>[[#Triangles|triangles]]</code>; <code>Pos</code> is in world [[unit]]s; <code>Norm</code> is used to smooth the surface of the model ({{todo|How?}}).
; <code>end</code>
: Ends the data block.


[[Category:Modeling]]
[[Category:Modeling]]
[[Category:Technical]]
[[Category:Glossary]]

Revision as of 16:39, 5 January 2009

The StudioMDL Data file format stores 3D geometry data in ASCII for analysis and compilation by studiomdl. SMD files are usually generated by an SMD exporter plug-in for a given model editor package.

The format is carriage return sensitive: 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". There is no support for comments.

Types

Reference
A complete snapshot of the model, including one frame of animation to define the default pose. Also used for collision meshes.
header
nodes
skeleton
triangles
Animation
A single skeletal animation.
header
nodes
skeleton
Vertex
For flex animation. Usually has extension .vta. Precise structure unclear.
header
nodes
skeleton
vertexanimation

Data blocks

Here are the components of an SMD file, considered in order:

Tip.pngTip:Unless otherwise noted all integer values begin at 0 and all floating point values are limited to six decimal places.

Header

Simply:

version 1

Nodes

A list of all the bones in the model.

Note.pngNote:Bones without attached vertices will not be compiled.

A root bone with one child:

nodes
0 "root" -1
1 "child" 0
end
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.
end
Ends the data block.

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.

Note.pngNote:There can only be one animation in each SMD.

This code makes 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
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).
Tip.pngTip: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.
end
Ends the data block.

Triangles

All of the polygons in the model by their three vertices. Included in each polygon is its UV co-ordinates and envelope weights.

Note.pngNote:Source's polygons are one-sided. The active face is the one around which the vertices can be traced clockwise.

This code represents 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
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
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
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
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
triangles
Begins the triangle block.
<material>
Defines the start of a new triangle and the material to apply to it. Anything after a '.' (e.g. a file extension) is ignored. Do not enclose in quotes and do not include a path ($cdmaterials will provide one).
<int|Parent bone> <float|PosX PosY PosZ> <normal|NormX NormY NormZ> <normal|U V> <int|links> <int|Bone ID> <normal|Weight> [...]
Defines a vertex. Pos is in world units. Norm is used to smooth the surface of the model (
Todo: How?
). U and V are the vertex's UV map co-ordinates.
The final three options are optional: they override <Parent bone> to define a series of weighted envelopes. Bone ID and Weight are repeated for each link. If the weights do not add up to 1, any remaining value is placed on <Parent bone>.
end
Ends triangle block.

Vertexanimation

Position of vertices in various morph targets (for flex animation). Although this block uses the same time keyword as skeleton, each 'frame' is a discrete shape: transitions between them are created on-demand by the engine.

Warning.pngWarning:The precise structure of this block is unclear. It is known that a skeleton block is required elsewhere in the file, though all frames in it appear to be the same!
vertexanimation
Begins the vertex animation block.
time <int>
Begins a morph target. It is unclear how many or even which vertices should be included (though it's a safe bet that the modified ones are among them).
<int|ID> <float|PosX PosY PosZ> <normal|NormX NormY NormZ>
A vertex. Its ID is defined by its position in triangles; Pos is in world units; Norm is used to smooth the surface of the model (
Todo: How?
).
end
Ends the data block.