DMX
DMX (Data Model eXtensible?) is a binary file format used in newer Valve technologies. It appears to be a generic replacement for ASCII formats like SMD or VDF. Currently it has two known uses: Particle systems (.pcf
) and model source data (.dmx
).
DMX has several advantages over VDF. It is:
- Efficient, especially when storing large ints or accurate floats
- Generic, and able to store most memory structures
- Robust, since it does not have to worry about delimiters, line breaks or unclosed quote blocks
Using DMX
With DMX being a binary format, it is not practical either to infer how a given file works from reading it, or to alter one by hand. When the tools for reading/writing them aren't publicly available, this is a problem!
Models
DMX model source files are generated by vsdmxio
, which only available publicly as a Maya plugin (sourcesdk/maya/2009/plug-ins/valveSource/
). Some editing options are available with the Source 2009 SDK tool dmxedit
however, including export to OBJ (unweighted, no animations).
To use dmxedit:
- Create an empty file called
vs.lua
in the SDK binaries folder. This is probably meant to contain commands that are executed every time you run the tool. - You must then create a LUA file containing the actions you want to perform. Here is a simple example that exports to OBJ:
Load( "<path_to_dmx>" )
Save("<export_path>.obj")
- Perform
dmxedit myfile.lua
to run the script.
If export a mesh DMX to OBJ you will get a single file. If you export a morph DMX you will get one OBJ for each flex animation that was in the file. If you chose an animation you will get nothing; it seems that dmxedit doesn't support animations.
Programming
Handling DMX files has many similarities to handling KeyValues. The two big architectural differences are that:
CDmxElement
objects contain eitherCDmxAttribute
objects, which hold actual data, or moreCDmxElement
s. Arrays are possible in both cases.- Values are accessed through a single templated function, not lots of different ones.
For a full list of attributes, see the bottom of public\datamodel\dmattributetypes.h
.

CUtlString
objects, not char
!Iterator
This code will print string, int, float and bool values in the given DMX to the console.
#include "cbase.h"
#include "dmxloader/dmxloader.h"
#include "dmxloader/dmxelement.h"
void IterateDmxElement(CDmxElement* pRoot)
{
for (int i=0;i<pRoot->AttributeCount();i++)
{
CDmxAttribute* pCur = pRoot->GetAttribute(i);
CDmxElement* subElem;
Warning( "%s: ",pCur->GetName() );
switch (pCur->GetType())
{
case AT_ELEMENT:
subElem = pCur->GetValue<CDmxElement*>();
if (subElem)
IterateDmxElement(subElem);
break;
case AT_STRING:
Msg( "STRING | %s\n",pCur->GetValue<CUtlString>().Get() );
break;
case AT_INT:
Msg( "INT | %i\n",pCur->GetValue<int>() );
break;
case AT_FLOAT:
Msg( "FLOAT | %f\n",pCur->GetValue<float>() );
break;
case AT_BOOL:
Msg( "BOOL | %s\n",pCur->GetValue<bool>() ? "true" : "false" );
break;
default:
Msg("Unknown type %i\n",pCur->GetType());
break;
}
}
}
CON_COMMAND(dmx_iterate, "Prints a DMX file to the console")
{
DECLARE_DMX_CONTEXT();
CDmxElement* DMX = (CDmxElement*)DMXAlloc( 50000000 );
if (UnserializeDMX(args[1],"MOD",false,&DMX))
{
IterateDmxElement(DMX);
}
else
Warning("Could not read DMX file %s\n",args[1]);
}