MDL ASCII format files are text files of decompiled or uncompiled models.
|Table of Contents|
An Ascii MDL file consist of a header, a single geometry block holding all meshes and optional animations blocks.
Some model naming rules are documented here: https://neverwintervault.org/project/nwnee/other/mdl-naming-rules
Every line starting with a
# is considered a comment. Most mdl files start with a comment line indicating the date and the program used for its creation.
This line is a reference to the file used by the 3D modeling program which the model was created in. Unlike the name suggests it is irrelevant to the game engine and often times contains only the value
ambient 1.0 0.0 0.0
Colors in mdl file are always defined as RGB values in the range of [0.0, 1.0]
Whenever something is explicitly not existing, like a texture or the parent of a node it must be declared as NULL. Leaving an empty value is considered invalid.
parent NULL # No parent
bitmap NULL # No texture
A Dummy is a single point in space without any data - no geometry, no surface, no volume, nothing. Therefore it is never rendered. Dummies are used to group objects or indicate special locations to the engine like target coordinates for spells and projectiles.
Every model always has a dummy as its first node which:
- Has to have the same name as the file (minus the file extension)
- Mustn't have a parent
The name of this objects the parent node. NULL if none.
position <X> <Y> <Z>
Position of the node relative to its parent. This property can be animated.
orientation <X> <Y> <Z> <A>
The rotation of this node relative to its parent, in axis-angle representation. The first three values define the axis, the fourth defines an angle in radian. This property can be animated.
Uniform scale of this object. This property can be animated.
wirecolor <R> <G> <B>
This property seems to be present for all objects, but seems to be unused.
These nodes are used as targets for certain emitter types. They are always children of those emitters and indicate the target locations for Lightning or Bezier type emitters.
In addition to all properties mentioned here, reference nodes have all properties of a Dummy.
The name of another MDL file without file-extension.
Exact purpose and usage unknown. They occur in some visual effects, but they behave exactly like normal dummy nodes and have the same properties.
Trimeshes inherit all attributes from Dummys in addition to their own.
Alpha value controlling transparency. Valid values are floating point numbers within [0.0, 1.0] - 0.0 being fully transparent and 1.0 fully opaque. This property can be animated.
ambient <R> <G> <B>
OpenGL GL_Ambient material parameter.
For light-rays. Light rays cannot be made specifically for a tile, as tiles can rotate. Instead a different kind of shadow was created where the shadow volume is rendered at an alpha value and a specific color. To create shadow volumes, make a group of simple triangles above the camera level and enable this flag.
Specifies the texture to be used by this node. The value
NULL means to texture. Valid file formats include:
- MTR: Material file
DDS: Direct Draw Surface
TGA: Truevision TGA
PLT: Packed Layer Texture
MTR files take precedence over image textures and may overwrite textures specified in the MDL. If a txi file with same name is present it will be loaded as well.
center <X> <Y> <Z>
Unused, pivot point of the object.
diffuse <R> <G> <B>
Material diffuse color. Default value when omitted: (0.8, 0.8, 0.8)
Enhanced Edition only. Specifies a material file (*.mtr), which allow the specification of shaders, additional textures and parameters.
selfillumcolor <R> <G> <B>
Makes the mesh glow without actually acting as a light source. It most likely corresponds to the GL_EMISSION material parameter in OpenGL. This property can be animated.
Note: In older mdl files this parameter might be spelled wrongly as
seTfillumcolor. (Pstemarie) The mispelling of this parameter is one of the primary reasons that older models fail to compile using nwnmdlcomp.
Controls whether this objects should cast a shadow. This attribute is frequently used in conjunction with the Render attribute to create a low-poly mesh solely for the purpose of casting shadows. Valid values are either 0 (disabled) or 1 (enabled).
Note: A number of community made models use "True" and "False" as values.
TODO. Shininess requires a matching texture information file (*.txi).
specular <R> <G> <B>
Material specular color, however this has no effect. Default value when omitted: (0.2, 0.2, 0.2)
Controls whether this object should be rendered. The geometry will still be loaded to the memory and casts shadows, even if this is unchecked. This is frequently used in conjunction with the Shadow attribute to create a low-poly shadow volume object. Valid values are either 0 (disabled) or 1 (enabled).
Note: A number of community made models use "True" and "False" as values.
Enhanced Edition only. Valid values:
NormalAndSpecMappedCurrently the default shaders do not use normal and specular mapping. To enable normal and specular mapping it is necessary to switch to another render path by adding this renderhint to the mdl file. This will automatically choose the matching shader, depending on the type of geometry node
/ NormalTangents (either of the two, can be used interchangeably)
Instructs the game to generate tangent and handedness vertex data for the associated model(s), provided that they are uncompiled and no tangent and handedness data exist. Also makes the game choose a shader with normal mapping enabled to render this content. Note: The renderhint can also be specified in a material file.
Only relevant for tilesets and controls ground mapping: When a model with this flag is rotated, the engine rotates the uv coordinates back to the original position. This avoids texture seams on tile edges.
This property is only relevant for tiles. It controls whether this mesh will turn invisible to offer a clear line of sight on the character. Possible values:
|0||Disabled||This object will never fade|
|1||Fade||This object will fade|
|3||Neighbor||This object will fade together with objects in neighboring tiles|
As transparency can be extremely costly to calculate from alpha values on a texture, this property gives the engine priority values of transparent objects. An object with a transparency hint of 1 will be rendered after an object that has a value of 0. This does not work on dynamic objects, it only affects static objects
Every lines defines a single vertex. The Faces section on a node references the indices of three vertices for every face.
Every lines defines a single texture vertex (tvert). They are 2-dimensional - the last value is always 0. The Faces section on a node references the indices of three tverts for every face.
Each line defines a triangle:
- The first three values
(v1 v2 v3) each reference a vertex from the vertex list. This is the index, not the actual coordinate.
- The 4th value
(s)defines the shading group the face belong to. All neighboring faces belonging to same group will be rendered as smooth.
- The next three values
(uv1 uv2 uv3)each reference a texture vertex (uv-vertex) from the tvert list. Again is the index, not the actual coordinate.
- The last value
(m)defines a material index. This is only relevant when creating walkmeshes for tiles and determines the surface type of this face.
Vertex colors. Each line contains the color for the corresponding vertex in the vertex list, as such the number of colors must match the number of vertices. Vertex colors are not used by the default shaders.
Per-vertex normals. Each line contains the normal for the corresponding vertex in the vertex list, as such the number of normals must match the number of vertices.
Per-vertex tangent data. Each line contains the value for the corresponding vertex in the vertex list, as such the number of tangents must match the number of vertices.
- The first three values defines the tangent vector
- The fourth value defines the binormal/ bitangent sign
Danglymeshes are Trimeshes which are "bouncy" or "dangly" and are affected by environmental effects like wind, character movement and visual effects.
In addition to their own set of attributes, Danglymeshes inherit all attributes from Trimeshes.
Determines how quickly the vertices move and how fast they come to a rest.
This value can be up to 59 before the mesh begins to jiggle incorrectly. At 59.5 the mesh may spasm sporadically. At 60 or above, the mesh will jiggle insanely for up to 1 second and then no longer jiggle, becoming locked at the starting position.
Tile grass (as created by walkmesh surface material 3) uses effects equivalent a hardcoded value greater than 60. It appears to be the only thing which can use this high a value.
The ’tension’ in the object, restricting movement.
A tight object is difficult to move by wind. Tile grass may have an approximate tightness of 50 or more.
Determines show far the vertices are allowed to move. This is further restricted by the constraints.
The value appears to be approximately 1/2 meter per unit.
Each line contains the constraints for the corresponding vertex in the vertex list, as such the number of constraints must match the number of vertices.
Constraints act as a multiplier for the displacement value and range from 0 to 255, with their value equating to the multiplier range of 0 to 1.
If the maximum displacement is set to 2, then the associated vertex painted with 255 will be allowed to move approximately 1 meter during maximum strength wind.
Skinmeshes are Trimeshes with additional weight parameters to support skeletal animations. As such they possess all properties of a Trimesh.
Every skinmesh must specify weights which influence its movements. Each line contains the weights for the corresponding vertex in the vertex list, as such the number of entries must match the number of vertices.
- Every line consists of
(name, weight)tuple, each defines the influence a node has over a single vertex.
- A line MUST have at least one
(name, weight)tuple. It mustn't be empty.
- A line MUSTN'T have more than four
- The weights are floating point numbers in the range of [0.0, 1.0]
- The sum of weights of must be 1.0 for each line.
Animeshes are Trimeshes with animated UV coordinates or vertices. In the geometry section of a model they have exactly the same properties as Trimeshes.
|TODO: Force Symphony to edit this: MDL ACSII Emitter Nodes|
This controls whether this light affects dynamic objects, i.e. characters. Disabling this will prevent this light from producing shadows with dynamic objects, but it will in turn improve performance. A less strict version of the Shadow setting.
Controls if the light is only an ambient light source or if it is directional as well.
color <R> <G> <B>
RGB light color.
Note: This value has no effect on tile lights (names ending with ml1, ml2) as that color is set by the module builder in the toolset.
Important for tile lights. Should be 0 for main lights and 1 for animated lights. Use this instead of isDynamic, which is outdated.
When a light is loaded or dropped from a scene, the light will flick on and off suddenly. If this check is on, the light will take a moment to fade on or off for a better overall feel. In some cases it’s best to have this un-checked, for things like spells where you want the light to be at it’s brightest as soon as it appears.
Radius in centimeters for all lens-flares cast by this light. The default value of 0 deactivates lens-flares. Used in conjunction with Flare Colorshifts, Flare Positions, Flare Sizes and Texture Names
Note: This value has no effect on tile lights as they can't have lens-flares. The flare radius is specified in cm as opposed to meters for other distance values.
<R> <G> <B>
<R> <G> <B>
A list of sizes for lens-flares. The actual flare sizes depend on the texture size, these values will scale the texture. Their number must match the amount of Flare Colorshifts, Flare Positions and Texture Names. This property will have no effect if Flare Radius is set to zero.
Outdated, used nDynamicType instead. Important for tile lights. Should be 0 for main lights and 1 for animated lights.
This property helps the engine in preventing the use of too many lights that affect dynamic objects. In order to know which lights should be culled first a priority is assigned to each light, ranging from 1-5, with 1 being the highest priority. This property is related to the light count setting in the game.
This is the general scheme:
- Global Ambient Lighting, Sun & Moon lights
- Torches & light spells
- Spells, general lights
- Un-needed tile lights
- Other un-needed lights (e.g. weapons)
Light intensity or brightness. Default value for Bioware SourceLights and MainTileLights is 1.
Light radius in metres.
Determines if this light is capable of producing shadows at all. A stricter version of the Affect Dynamic property.
A list of texture names for lens-flares. Their number must match the amount of Flare Sizes, Flare Positions and Flare Colorshifts. Only TGA or DDS textures are allowed. This property will have no effect if Flare Radius is set to zero.
Default textures: fxpa_lensring or fxpa_lensflare
Axis Aligned Bounding Boxes in a tree structure for collision detection.
- The first three values define the minimum coordinates of the bounding box
- The next three values define the maximum coordinates of the bounding box
- The last value defines the face index, if the node is a leaf (-1 otherwise)
An mdl file may contain multiple animation blocks with the animation name determining its usage.
|newanim <animation_name> <model_name>|
node <node_type> <node_name>
node <node_type> <node_name>
Length of the animation in seconds.
Time in seconds where the animation overlaps with other animation to ensure a smooth transitions.
The animations entry point. This is useful for only animating part of the model and having the rest play a different animation. This used in the torch an shield holding animations to only influence the movement of a single arm.
event <time> <event_name>
event <time> <event_name>
Each animation may have a list of events. They typically trigger sounds or visual effects. The time value mustn't be larger then the animation length.
Trigger all Explosion type emitters.
Also produces a burst of wind using the blast properties of the emitter node. Those properties include radius and length, so a gust of wind can be managed.
|blur_end||End of Weapon Blur effect|
|blur_start||Start of Weapon Blur effect|
|cast||Spell activate effect (depends on spell)|
|draw_arrow||Sound: Draw Arrow|
|draw_weapon||Sound: Draw Weapon|
|hit||Weapon hit effect (depends on weapon)|
|snd_footstep||Sound: Footstep (depends on surface material)|
|snd_hitground||Sound: Creature hits ground|
Animation nodes reference nodes in the geometry block. The order and the name of the animation nodes must match the ones in the geometry block. However the node type may differ.
A node's properties are animated by specifying either a single value or a list of keys.
If the animation contains only a single state, they are specified the same way as in the geometry block, e.g.
position X Y Z. In this case the values will be held for the entire duration of the animation.
A list of keys, each specifying the value at a certain point in time. If a property is animateable, appending key to its name indicates the beginning of a key-list. Click here for a list of animateable properties.
The correct way to specify keyframes is enclosing them with
endlist. However some tools will instead use
positionkey <keycount> and omit the
Animates the position of a node. Each line specifies the position of the node at time
t. All values are floats and relative to the parent node. The time value mustn't be larger then the animation length.
Animates the orientation of a node. Each line specifies the orientation of the node at time
t. The angles are in Axis-Angle format and relative to the parent node. The time value mustn't be larger then the animation length.
This a list of animateable properties for each node type.