Difference between revisions of "MDL File Format"

From HIVE
Jump to navigation Jump to search
 
(8 intermediate revisions by the same user not shown)
Line 3: Line 3:
  
 
MDL is the text file format of Warcraft 3 3D models (for the binary format, see [[MDX_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 <code>TVertex</code> chunks in one <code>Geoset</code>, <code>ParticleEmitter2</code>'s that emit Team Glow using the <code>ReplaceableId</code> fields, certain <code>Light</code> intensity values, and other such obscurities.
 +
 +
= Comments =
 +
Comments use a double forward slash, and are of the form:
 +
 +
<code>// This is a comment</code>
 +
 +
Most converters will automatically insert a comment on each node's <code>ParentId X,</code> 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)==
 +
<pre>
 +
//This model was converted from MDX by ogre-lord's Java MDX API and Retera's Java MDL API
 +
</pre>
 +
==Matrix Eater (save timestamp)==
 +
<pre>
 +
// Saved by Retera's MDL Toolkit on Fri Feb 16 20:18:29 EST 2018
 +
</pre>
 +
==Magos War3 Model Editor (fanmade MDX -> MDL conversion, save timestamp)==
 +
<pre>
 +
//+-----------------------------------------------------------------------------
 +
//| Footman.mdl
 +
//| Generated by War3 Model Editor v1.07
 +
//| Friday, February 16 2018 20:22:40
 +
//| http://www.magosx.com
 +
//+-----------------------------------------------------------------------------
 +
</pre>
 +
==MDLX Converter (fanmade MDX -> MDL conversion)==
 +
<pre>
 +
// Converted Fri Jan 22 23:02:40 2016
 +
// MdlxConv Version Jun 29 2010.
 +
</pre>
 +
==YobGul's War3FileConverter (MDX -> MDL using game.dll, timestamp)==
 +
<pre>
 +
// MDLFile version Jun 27 2002 20:34:57
 +
// Exported on Sun Aug 31 10:33:18 2008
 +
</pre>
 +
==MdlVis==
 +
<pre>
 +
//Modified with MdlVis.
 +
</pre>
 +
 +
=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:
 +
 +
<pre>
 +
Version {
 +
FormatVersion 800,
 +
}
 +
</pre>
 +
 +
=Extents=
 +
Insofar as the MDL is concerned, in places where Extents may be listed, either a <code>BoundsRadius</code> or a <code>MinimumExtent</code> and <code>MaximumExtent</code> 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 <code>BoundsRadius 0</code> as though this encodes a special magic value, but this is not true of all tools.
 +
 +
==Examples==
 +
No bounds radius:
 +
<pre>
 +
MinimumExtent { -398.074, -378.684, -70.7763 },
 +
MaximumExtent { 365.174, 399.203, 1040.87 },
 +
</pre>
 +
 +
With bounds radius:
 +
<pre>
 +
MinimumExtent { -160.357, -173.089, -53.7329 },
 +
MaximumExtent { 172.467, 160.42, 197.855 },
 +
BoundsRadius 239.729,
 +
</pre>
 +
 +
=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 <code>NumGeosets 3,</code> but it is preferable to load any number of <code>Geoset</code> blocks, so that a user can add more without consequence.
 +
 +
So, significant fields for a parser here include <code>BlendTime</code>, and the extents. For parsing <code>Extents</code>, see the <code>Extents</code> section.
 +
 +
==Example==
 +
 +
<pre>
 +
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,
 +
}
 +
</pre>
 +
 +
=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 <code>Anim</code> followed by the animation sequence name.
 +
 +
The <code>Anim</code> block's contents will be the time interval denoted simply with <code>Interval { STARTTIME, ENDTIME }</code>, followed by option flags, and ending with a set of extents specific to the animation.
 +
 +
Known possible flags:
 +
- <code>Rarity X</code> will assign the likelihood to X of secondary animations to play.
 +
- <code>MoveSpeed X</code> 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.
 +
- <code>NonLooping</code> will assign an animation not to loop, such as for an attack animation.
 +
 +
==Example==
 +
<pre>
 +
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,
 +
}
 +
}
 +
</pre>
 +
 +
Again, we see that the header <code>Sequences 3</code> 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 <code>GlobalSeqId X</code> where X is a 0-based index into the <code>GlobalSequences</code> 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==
 +
<pre>
 +
GlobalSequences 8 {
 +
Duration 3333,
 +
Duration 6000,
 +
Duration 5200,
 +
Duration 4367,
 +
Duration 733,
 +
Duration 500,
 +
Duration 400,
 +
Duration 1100,
 +
}
 +
</pre>
 +
 +
=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):
 +
<pre>
 +
Bitmap {
 +
Image "Textures\HeroBladeMaster.blp",
 +
}
 +
</pre>
 +
 +
Or the texture can define a reference to a ReplaceableId:
 +
<pre>
 +
Bitmap {
 +
Image "",
 +
ReplaceableId 2,
 +
}
 +
</pre>
 +
 +
In this case, <code>ReplaceableId</code> set to 1 will load <code>ReplaceableTextures\TeamColor\TeamColorXX.blp</code> based on Player Id, and when set to 2 will similarly load <code>ReplaceableTextures\TeamGlow\TeamGlowXX.blp</code>.
 +
 +
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 <code>WrapWidth</code> or <code>WrapHeight</code>. These will cause the texture to repeat, so that the coordinates in the <code>TVertices</code> 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==
 +
<pre>
 +
Textures 3 {
 +
Bitmap {
 +
Image "Textures\HeroBladeMaster.blp",
 +
}
 +
Bitmap {
 +
Image "",
 +
ReplaceableId 2,
 +
}
 +
Bitmap {
 +
Image "Textures\Ice3b.blp",
 +
WrapWidth,
 +
WrapHeight,
 +
}
 +
}
 +
</pre>
 +
 +
=Materials Block=
 +
 +
These are the system on top of <code>Textures</code> that allows you to specify blending modes and other special features.
 +
As well as being used for <code>Geoset</code>s, Materials are also notable in that they are used for <code>RibbonEmitter</code> nodes.
 +
 +
Materials consist of one or more <code>Layer</code>s, but also can have tags of their own:
 +
- <code>PriorityPlane X</code> 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).
 +
- <code>ConstantColor</code> will inform the <code>Material</code> that it should use the related <code>GeosetAnim</code>'s Color values, or use the Color values of a RibbonEmitter that uses the Material.
 +
- <code>SortPrimsFarZ</code> is another possible Material flag [...?]
 +
- <code>SortPrimsNearZ</code> is another possible Material flag, but unlike <code>SortPrimsFarZ</code> I do not recall ever seeing it on any existing Warcraft III game models
 +
- <code>FullResolution</code> is another possible Material flag that probably has to do with BLP mip-mapping.
 +
 +
=TextureAnims Block=
 +
 +
=Geoset Blocks=
 +
 +
=GeosetAnim Blocks=
 +
 +
=Node Blocks=
 +
 +
==Bone Block==
 +
 +
==Light Block==
 +
 +
==Helper Block==
 +
 +
==Attachment Block==
 +
 +
==ParticleEmitter Block==
 +
 +
==ParticleEmitter2 Block==
 +
 +
==RibbonEmitter Block==
 +
 +
==EventObject Block==
 +
 +
==CollisionShape Block==
 +
 +
=Pivot Points=
 +
 +
=Camera Blocks=

Latest revision as of 07:28, 17 February 2018


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 Geosets, Materials are also notable in that they are used for RibbonEmitter nodes.

Materials consist of one or more Layers, 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 the Material that it should use the related GeosetAnim's Color values, or use the Color values of a RibbonEmitter that uses the Material.
- SortPrimsFarZ is another possible Material flag [...?]
- SortPrimsNearZ is another possible Material flag, but unlike SortPrimsFarZ I do not recall ever seeing it on any existing Warcraft III game models
- FullResolution is another possible Material flag that probably has to do with BLP mip-mapping.

TextureAnims Block

Geoset Blocks

GeosetAnim Blocks

Node Blocks

Bone Block

Light Block

Helper Block

Attachment Block

ParticleEmitter Block

ParticleEmitter2 Block

RibbonEmitter Block

EventObject Block

CollisionShape Block

Pivot Points

Camera Blocks