MDL File Format
MDL is the text file format of Warcraft 3 3D models (for the binary format, see MDX_File_Format).
Preface/About
Unlike the MDX binary format, the MDL format is badly supported by fan-made tools because the Warcraft III game engine usually will not load imported MDL models unless they are present in use on a unit physically placed on the map at game start. Since very few users are aware that the game is even capable of loading and displaying an imported MDL model, support with fan tools is limited. The format generally was used for manual user edits when Warcraft III modeling had less available fan-made tools, and only in the first few years after the game was released. Even then, most users edited MDL files only with the intention of then converting the MDL file to an MDX before using it.
There is almost no fan-made tool capable of parsing the entire MDL specification and converting it to an MDX to this day other than YobGul's File Converter which uses the native game.dll from Warcraft III to convert the model with Blizzard's own code.
Many tools approximate, such as Magos's War3 Model Editor or MDLX Converter, but will suffer data loss on models with multiple TVertex
chunks in one Geoset
, ParticleEmitter2
's that emit Team Glow using the ReplaceableId
fields, certain Light
intensity values, and other such obscurities.
Comments
Comments use a double forward slash, and are of the form:
// This is a comment
Most converters will automatically insert a comment on each node's ParentId X,
field, noting the name of the node's parent for user reference.
Below are a list of tool-specific, known automatically generated comments.
Matrix Eater (fanmade MDX -> MDL conversion)
//This model was converted from MDX by ogre-lord's Java MDX API and Retera's Java MDL API
Matrix Eater (save timestamp)
// Saved by Retera's MDL Toolkit on Fri Feb 16 20:18:29 EST 2018
Magos War3 Model Editor (fanmade MDX -> MDL conversion, save timestamp)
//+----------------------------------------------------------------------------- //| Footman.mdl //| Generated by War3 Model Editor v1.07 //| Friday, February 16 2018 20:22:40 //| http://www.magosx.com //+-----------------------------------------------------------------------------
MDLX Converter (fanmade MDX -> MDL conversion)
// Converted Fri Jan 22 23:02:40 2016 // MdlxConv Version Jun 29 2010.
YobGul's War3FileConverter (MDX -> MDL using game.dll, timestamp)
// MDLFile version Jun 27 2002 20:34:57 // Exported on Sun Aug 31 10:33:18 2008
MdlVis
//Modified with MdlVis.
Version Block
This block is presumably used to indicate version. Since Warcraft III's model formatting has not changed much in about 15 years, almost all models ever observed will be version 800.
The block usually looks like this:
Version { FormatVersion 800, }
Extents
Insofar as the MDL is concerned, in places where Extents may be listed, either a BoundsRadius
or a MinimumExtent
and MaximumExtent
pair may be given, or both. Specifics on which is actually accepted should include knowledge of the binary MDX, of which this format is an approximate, since it is illogical to include or exclude extents information where the binary will actually encode a value in all cases.
Many user tools seem to add BoundsRadius 0
as though this encodes a special magic value, but this is not true of all tools.
Examples
No bounds radius:
MinimumExtent { -398.074, -378.684, -70.7763 }, MaximumExtent { 365.174, 399.203, 1040.87 },
With bounds radius:
MinimumExtent { -160.357, -173.089, -53.7329 }, MaximumExtent { 172.467, 160.42, 197.855 }, BoundsRadius 239.729,
Model Block
This block denotes the model's name, number of each type of chunk, blend time, and bounds/extents.
Typically most MDL parsers will ignore the chunk counts here to allow users to add more manually without having to update the listed total count. For example, a model might have NumGeosets 3,
but it is preferable to load any number of Geoset
blocks, so that a user can add more without consequence.
So, significant fields for a parser here include BlendTime
, and the extents. For parsing Extents
, see the Extents
section.
Example
Model "HeroBladeMaster" { NumGeosets 9, NumGeosetAnims 6, NumHelpers 7, NumBones 52, NumAttachments 9, NumParticleEmitters2 2, NumRibbonEmitters 1, NumEvents 14, BlendTime 150, MinimumExtent { -398.0740051269531, -378.6839904785156, -70.77629852294922 }, MaximumExtent { 365.17401123046875, 399.2030029296875, 1040.8699951171875 }, BoundsRadius 0, }
Sequences Block
Generally speaking, this section stores a list the model's animations. Each one (similar to the MDX) is denoted by a name, as well as the start and the end of an interval in the timeline. Timeline units are in milliseconds, presumably the same as in the MDX.
The animations are each listed with Anim
followed by the animation sequence name.
The Anim
block's contents will be the time interval denoted simply with Interval { STARTTIME, ENDTIME }
, followed by option flags, and ending with a set of extents specific to the animation.
Known possible flags:
-Rarity X
will assign the likelihood to X of secondary animations to play. -MoveSpeed X
will assign the animation speed of a walk animation to X, at least for previewing in the 3DS Max Warcraft III Previewer. Experimentation could show whether this is overridden by, or used in conjunction with, the Unit Editor's Art setting for animation running/walking speed. -NonLooping
will assign an animation not to loop, such as for an attack animation.
Example
Sequences 3 { Anim "Stand - 4" { Interval { 18333, 19867 }, Rarity 5, MinimumExtent { -161.903, -156.059, -53.7325 }, MaximumExtent { 173.687, 147.152, 311.227 }, BoundsRadius 244.116, } Anim "Death" { Interval { 22000, 23900 }, NonLooping, MinimumExtent { -164.299, -189.177, -70.7763 }, MaximumExtent { 202.347, 146.761, 247.548 }, BoundsRadius 262.983, } Anim "Walk" { Interval { 28767, 29500 }, MoveSpeed 290, MinimumExtent { -140.486, -153.459, -24.7915 }, MaximumExtent { 185.56, 140.549, 232.482 }, BoundsRadius 244.91, } }
Again, we see that the header Sequences 3
in the example above encodes useless information that only makes the model harder to edit manually, so many fan-made converters will ignore it.
GlobalSequences Chunk
These are sequences that constantly play in a looping fashion during other animations. Their only data is their integer length on their own time track, and any animated (non-static) value can be given the line GlobalSeqId X
where X is a 0-based index into the GlobalSequences
list, and in such a case this will define the animated keyframe data in that entry to be on the global sequence timeline and not on the general animation timeline.
Example
GlobalSequences 8 { Duration 3333, Duration 6000, Duration 5200, Duration 4367, Duration 733, Duration 500, Duration 400, Duration 1100, }
Textures Block
This block is decently self-explanatory, and encodes a file path or replaceable ID in each entry.
The texture can define a reference to a BLP file (Note that non-BLP texture usage is not advisable, but may work in some tools):
Bitmap { Image "Textures\HeroBladeMaster.blp", }
Or the texture can define a reference to a ReplaceableId:
Bitmap { Image "", ReplaceableId 2, }
In this case, ReplaceableId
set to 1 will load ReplaceableTextures\TeamColor\TeamColorXX.blp
based on Player Id, and when set to 2 will similarly load ReplaceableTextures\TeamGlow\TeamGlowXX.blp
.
Other replaceable ID values exist. Common uses include the doodad Cliff Cave models, the physical "Cliff" models used in drawing the map terrain itself, and trees. Many tutorials on the Hive for dynamic texture loading will use the same replaceable ID as the Mountain Giant model, which is assigned dynamically based on an ability, and can be thus exploited to assign arbitrary model textures to a unit at run-time as long as a Destructable object is created for each texture.
Textures also may optionally have one or both of either WrapWidth
or WrapHeight
. These will cause the texture to repeat, so that the coordinates in the TVertices
chunk can go outside their normal allowed range of [0,1] and still return valid results (based on repeating the texture in either dimension, or both).
Example
Textures 3 { Bitmap { Image "Textures\HeroBladeMaster.blp", } Bitmap { Image "", ReplaceableId 2, } Bitmap { Image "Textures\Ice3b.blp", WrapWidth, WrapHeight, } }
Materials Block
These are the system on top of Textures
that allows you to specify blending modes and other special features.
As well as being used for Geoset
s, Materials are also notable in that they are used for RibbonEmitter
nodes.
Materials consist of one or more Layer
s, but also can have tags of their own:
-PriorityPlane X
will assign the Z-depth value while rendering to X, which can force a Material to be always-on-top or always-behind other objects. Unfortunately, I seem to recall this only works for specific FilterMode(s). -ConstantColor
will inform theMaterial
that it should use the relatedGeosetAnim
's Color values, or use the Color values of a RibbonEmitter that uses the Material.