MODELDEF
MODELDEF is the lump which defines models used in hardware-accelerated ports.
![]() |
Warning: This feature does not work in ZDoom but in its OpenGL children ports. |
MODELDEF lumps are cumulative; multiple can exist in the same project and the engine parses all of them. Unlike in WADs, in directory-based archives, multiple files with the same name are unacceptable. To workaround this, each MODELDEF file should be given a unique extension, e.g, modeldef.boxes or modeldef.cars. A better method of organization is to use the #include directive in the MODELDEF file while providing the full path to the target file. Example:
#include "modeldefs/boxes.txt" #include "modeldefs/cars.txt"
The above assumes a directory that is called modeldefs/ which exists in the root directory of the archive. In it, are the files boxes.txt and cars.txt which contain model definitions.
Model Definition Overview
Models with named frames
MD2s normally have actual frame names so you can reference them by name.
Model <ActorName> { Path <"path"> Model <model index> <"model file"> Skin <model index> <"skin file"> Scale <X scale> <Y scale> <Z scale> Frame <XXXX> <X> <model index> <"frame name"> }
Models with named animations
(New from 4.10.0)
IQMs can hold multiple named animation sequences, so you can reference frames by the name of the animation and a frame index in it, separated by a colon.
Model <ActorName> { Path <"path"> Model <model index> <"model file"> Skin <model index> <"skin file"> Scale <X scale> <Y scale> <Z scale> Frame <XXXX> <X> <model index> <"animation name:frame number"> }
For models with unnamed frames
MD3s do not contain any useful names that you can use. You would use frame indexes instead of frame names. More information below.
Model <ActorName> { Path <"path"> Model <model index> <"model file"> Skin <model index> <"skin file"> Scale <X scale> <Y scale> <Z scale> FrameIndex <XXXX> <X> <model index> <frame number> }
More detailed information
In the two above examples, <ActorName> is the name of the actor (as used in DECORATE, etc), <XXXX> is the sprite lump (example POSS), and <X> is the sprite frame (example A). The rest can be found in the Properties section.
The Frame property does not need to use an actual sprite name. It can be an arbitrary set of letters or numbers (MODL or MDLA are some of the commonly used examples) and it doesn't have to correlate to any real sprite (but it can, it won't affect anything), because the sprite itself will never be rendered, it's just a way of attaching models to actors. There are a few limitations to that rule, however:
- If a non-existent sprite name is used as the very first frame in an actor's Spawn sequence, it won't be spawned at map start and will instead be replaced with an error marker. This will happen even if the actor has a model attached to it, despite the fact that that sprite isn't used in the game and won't be drawn. This can be circumvented by using an existing sprite name, or by adding TNT1 A 0 as the very first frame of Spawn.
- Similarly, using a non-existent sprite name as the very first frame of the Ready sequence in weapons will also cause issues, even if you attach a model do it.
- Using non-existent sprite names everywhere will flood the console with errors if running GZDoom with -developer 2 parameter, which defines much stricter rules for potential issues. It doesn't cause any issues in practice, however.
- Models can't be attached to TNT1 A 0, since TNT1 is an internal shorthand for disabling the rendering of the object completely.
Flags and Properties
Flags
There are a number of flags that you can use in MODELDEF.
- PITCHFROMMOMENTUM
- Adjusts the model's pitch to match the momentum of the actor; useful for rocket projectiles.
- IGNORETRANSLATION
- Ignores the actor's translation.
- INHERITACTORPITCH (deprecated)
- Model's pitch adjusts to match the actor's pitch, deprecated because of the unintended pitch inversion and bad name choice
- INHERITACTORROLL (deprecated)
- Model's roll, adjusts to match actor's roll. Same as USEACTORPITCH, deprecated because of bad name choice.
- INTERPOLATEDOUBLEDFRAMES
- Workaround to smooth the model interpolation of actors that use the same frame twice in a row. Most of the standard Doom monsters do this in their see state.
- ROTATING
- Makes the model rotate, useful for pickup models a la Quake 3. Related properties must be defined AFTER this flag.
- NOINTERPOLATION
- Forces uninterpolated animation.
- USEACTORPITCH
- Model's pitch adjusts to match actor's pitch.
- USEACTORROLL
- Model's roll, adjusts to match actor's roll.
- DONTCULLBACKFACES
- Forcefully disables backface culling.
- USEROTATIONCENTER
- Makes Rotation-Center affect actor angles (the property must be set AFTER this flag to work). Useless unless any of the actor rotation flags are also used.
- NOPERPIXELLIGHTING
- Disables per-pixel lighting on the model.
- SCALEWEAPONFOV
- Scales the weapon's model along with the user's FOV to reduce distortion.
- MODELSAREATTACHMENTS
- Model indices will be treated as belonging to the same armature as model index 0. Therefore each model will just get attached to the model and animation data at index 0. Each model needs to have the same exact armature or unwanted
- behavior may occur. Having this flag defined takes priority over the Animation property. This flag should be used especially if there are a lot of attachments like heads, hats, weapons, etc. This flag only has an effect on skeletal formats.
- CORRECTPIXELSTRETCH (New from 4.10.0)
- By default, models stretch when their pitch or roll changes, in a way that matches aspect ratio correction. This flag disables that behavior so the model always retains the same size without any distortion.
- Note: Although technically a bug, the stretching can nevertheless be useful, for example, to ensure that a beam-shaped model retains the same length in map units regardless of orientation.
Properties
- AngleOffset angle
- Changes model yaw angle by the given floating point value in degrees. Keep in mind this and the other angles are applied after scaling and offsets.
- Model model-index model-file
- Defines model to use. You can define multiple models to use with different indexes.
- Path path
- Path to model file in the ZIP/PK3. This parameter is entirely optional, its reason for existence is to avoid repeated typing of the path if it is used for the model itself and several skins. This will just get prepended to the specified names, so if it is left out, the ZIP/PK3's root will be used and all paths to the files have to be fully given with their respective properties.
- PitchOffset angle
- Changes model pitch angle by the given floating point value in degrees.
- Offset xoffset yoffset zoffset
- Sets actor x/y/z offsets.
- RollOffset angle
- Changes model roll angle by the given floating point value in degrees.
- Rotation-Center float float float
- Specify the x, y and z coordinate of the center of the rotation. Without either the ROTATING or USEROTATIONCENTER keywords, this does nothing
- Rotation-Speed float
- Specify the speed of the rotation. Without the ROTATING keyword, this and the other rotation properties do nothing
- Rotation-Vector float float float
- Specify the x, y and z component of the vector of the rotation
- Skin model-index skin-file
- Defines skin to use for the model of the same index. The skin-file can be of any format that ZDoom supports.
- SurfaceSkin model-index surface-index skin-file
- Defines skin to use for the specified MD3 surface index on model-index model. This can only be used on MD3 files, otherwise it gets ignored.
- Scale float float float
- Defines the x, y, and z scaling of the model.
- ZOffset float
- Adjusts the model's height, useful if you don't have access to a model editor.
- Animation animation-index model-file
- Defines the animation data to use for the model of the same index. This property only has an effect on skeletal formats such as IQM.
Examples
Simple one-frame example:
Model SteelCrate { Path "Models/Crate" Model 0 "Steelc.md2" Skin 0 "Steelc.png" Frame COL1 A 0 "frame01" }
An example of a walking animation for an MD2 model (uses frame names instead of frame numbers):
Model BloodHound // Name of actor in DECORATE { Path "models/bloodhound" // Path to model in PK3 Model 0 "bloodhound.md2" // Model index, model file Skin 0 "bloodhound.pcx" // Model index, texture (can be in any format supported by GZDoom) Scale 1.0 1.0 1.0 // Scale values Frame BHND A 0 "walk01" // The sprite lump, sprite frame, model index, name of frame Frame BHND B 0 "walk02" Frame BHND C 0 "walk03" Frame BHND D 0 "walk04" }
An example of a walking animation for an MD3 model (uses frame numbers instead of frame names):
Model InsaneCancer // Name of actor in DECORATE { Path "models/insanecancer" // Path to model in PK3 Model 0 "insanecancer.md3" // Model index, model file Skin 0 "insanecancer.png" // Model index, texture (can be in any format supported by GZDoom) Scale 1.0 1.0 1.0 // Scale values FrameIndex ICNC A 0 0 // The sprite lump, sprite frame, model index, frame number FrameIndex ICNC B 0 1 FrameIndex ICNC C 0 2 FrameIndex ICNC D 0 3 }
Multiple model example:
Model MultiModel { Path "Models/MyModel" Model 0 MyModel_Piece_1.md3 Skin 0 MyModel_Piece_1.jpg Model 1 MyModel_Piece_2.md3 Skin 1 MyModel_Piece_2.jpg Model 2 MyModel_Piece_3.md3 Skin 2 MyModel_Piece_3.jpg Model 3 MyModel_Piece_4.md3 Skin 3 MyModel_Piece_4.jpg Scale 1.0 1.0 1.0 Frame FRAM A 0 0 // All four models are drawn when you call frame "FRAM A" Frame FRAM A 1 0 Frame FRAM A 2 0 Frame FRAM A 3 0 }
Animation through multiple skins example using two model parts:
Model "PDA Model" { Path "models\PDA" Model 0 "PDA.md3" Skin 0 "pda.png" Model 1 "pdascreen.md3" Path "textures\models\PDA" //this redirects the path for the next file Skin 1 "pdas1.png" // Each redefinition includes the next frame of skin animation for this piece Scale 3.0 3.0 3.0 FrameIndex PDA1 A 0 0 // Both the frame and screen are pieced together FrameIndex PDA1 A 1 0 } Model "PDA Model" //re-defining the same actor for the next frame { Path "models\PDA" Model 0 "PDA.md3" Skin 0 "pda.png" Model 1 "pdascreen.md3" Path "textures\models\PDA" Skin 1 "pdas2.png" Scale 3.0 3.0 3.0 FrameIndex PDA1 B 0 0 // the next frame is defined FrameIndex PDA1 B 1 0 } Model "PDA Model" { Path "models\PDA" Model 0 "PDA.md3" Skin 0 "pda.png" Model 1 "pdascreen.md3" Path "textures\models\PDA" Skin 1 "pdas3.png" Scale 3.0 3.0 3.0 FrameIndex PDA1 C 0 0 FrameIndex PDA1 C 1 0 } Model "PDA Model" { Path "models\PDA" Model 0 "PDA.md3" Skin 0 "pda.png" Model 1 "pdascreen.md3" Path "textures\models\PDA" Skin 1 "pdas4.png" Scale 3.0 3.0 3.0 FrameIndex PDA1 D 0 0 FrameIndex PDA1 D 1 0 }
Brightmapped Example:
Model BrightmapModel { Path "Models/MyModel" Model 0 "MyModel.md3" Path "Textures/Models/MyModel/Skin" //this redirects the path for the next file Skin 0 "MyModel_Skin.png" //this must be defined as a brightmap in GLDEFS Scale 1.0 1.0 1.0 FrameIndex FRAM A 0 0 }
Notes
- The number of model 'pieces' used to be restricted to 4, but that limitation was lifted in GZDoom 4.6.0 and is no longer valid.
- Model skins can be brightmapped by placing all related skins in the TEXTURES folder of your pk3, and redefining the skin path appropriately. Brightmaps must then be declared within GLDEFS as normal.
- If you don't know how the frames in your model file are named, simply use FrameIndex instead of Frame. By using FrameIndex, all you have to do is supply the frame numbers, without having to worry about typing out the frame names correctly.
- When using FrameIndex, setting frame number to -1 disables rendering of the associated model.
- Naming a model or skin after the sprite it replaces will most likely result in issues.
- Using the Animation property together with assigning frames by name may not work as expected unless both models have the same number of animation sequences, in the same order, with the same number of frames each.
Multiple model animation issue
There is a known issue with defining an animation with multiple models used in the same frame: The frame has to be defined in full consecutively, otherwise only the last defined model animation plays properly. For instance, this sequence results in issues:
//first model FrameIndex FRAM A 0 0 FrameIndex FRAM B 0 1 FrameIndex FRAM C 0 2 //second model FrameIndex FRAM A 1 0 FrameIndex FRAM B 1 1 FrameIndex FRAM C 1 2
To work properly, it has to be reordered like so:
FrameIndex FRAM A 0 0 FrameIndex FRAM A 1 0 FrameIndex FRAM B 0 1 FrameIndex FRAM B 1 1 FrameIndex FRAM C 0 2 FrameIndex FRAM C 1 2
The model index order inside a frame does not matter.