DMX: Difference between revisions
TomEdwards (talk | contribs) m (→Programming) |
TomEdwards (talk | contribs) No edit summary |
||
Line 1: | Line 1: | ||
{{toc-right}} | |||
DMX | '''DMX''' (Data Model eXtensible?) is a [[W:Binary file|binary]] encoding of a [[Datamodel]] object. It is the sister format of [[KeyValues2]], which stores the same data in ASCII. The unreleased SDK tool '''dmxconvert''' can convert between the two formats. | ||
# '' | Compared to KeyValues2, DMX is: | ||
# '' | |||
# | # ''Small'', especially when storing large [[int]]s or accurate [[float]]s | ||
# ''Fast'', as values do not have to be converted to or from human-readable characters | |||
# ''Robust'', since it does not have to worry about delimiters, line breaks or unclosed quote blocks | |||
# ''Inscrutable'', because it contains native binary data | |||
DMX encoding is currently used for [[particle]] systems (<code>.pcf</code>) and [[model]] source data (<code>.dmx</code>). | |||
== Using DMX == | == Using DMX == |
Revision as of 11:10, 15 December 2010
DMX (Data Model eXtensible?) is a binary encoding of a Datamodel object. It is the sister format of KeyValues2, which stores the same data in ASCII. The unreleased SDK tool dmxconvert can convert between the two formats.
Compared to KeyValues2, DMX is:
- Small, especially when storing large ints or accurate floats
- Fast, as values do not have to be converted to or from human-readable characters
- Robust, since it does not have to worry about delimiters, line breaks or unclosed quote blocks
- Inscrutable, because it contains native binary data
DMX encoding is currently used for particle systems (.pcf
) and model source data (.dmx
).
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
!
Creating
#include "cbase.h"
#include "dmxloader/dmxloader.h"
#include "dmxloader/dmxelement.h"
CON_COMMAND( dmx_create, "Makes a simple DMX" )
{
DECLARE_DMX_CONTEXT();
CDmxElement* DMX = CreateDmxElement("");
CDmxAttribute* curAttr = DMX->AddAttribute("Hello");
curAttr->SetValue("world");
CUtlBuffer buf;
SerializeDMX(buf,DMX);
FileHandle_t fh = filesystem->Open("test.dmx","w","DEFAULT_WRITE_PATH");
filesystem->Write(buf.Base(),buf.TellPut(),fh);
filesystem->Close(fh);
}
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]);
}