DMX model: Difference between revisions
Jump to navigation
Jump to search
Note:All names are case sensitive.
mNo edit summary |
(details from Valve) |
||
Line 89: | Line 89: | ||
bool flipVCoordinates; // left-handed to right-handed? | bool flipVCoordinates; // left-handed to right-handed? | ||
// In the next three cases, the | // In the next three cases, the first array contains the location of each vertex on the model. | ||
// | // The second "Indices" array contains one entry one entry per vertex /per face/. | ||
Vector positions[]; | Vector positions[]; | ||
Line 103: | Line 101: | ||
int textureCoordinatesIndices[]; | int textureCoordinatesIndices[]; | ||
// Weightmapping; optional. The size of BOTH arrays is equal to ( sizeof(positions) * jointCount ) | // Weightmapping; optional. The size of BOTH arrays is equal to ( sizeof(positions) * jointCount ) | ||
float jointWeights[]; // weight | float jointWeights[]; // weight | ||
int jointIndices[]; // index in DmeModel::jointList (v18) or DmeModel::baseStates[0]::transforms (v1) | int jointIndices[]; // index in DmeModel::jointList (v18) or DmeModel::baseStates[0]::transforms (v1) | ||
Line 139: | Line 136: | ||
{ | { | ||
DmeTimeFrame* timeFrame; | DmeTimeFrame* timeFrame; | ||
Colour color; | Colour color; // SFM only | ||
CUtlString text; | CUtlString text; // SFM only | ||
bool mute; // | bool mute; // SFM only | ||
int frameRate; // typically 30 | int frameRate; // typically 30 | ||
void trackGroups[]; // only | void trackGroups[]; // SFM only | ||
DmeChannel channels[]; // two for each bone: position and rotation | DmeChannel channels[]; // two for each bone: position and rotation | ||
}; | }; | ||
Line 158: | Line 155: | ||
class DmeChannel | class DmeChannel | ||
{ | { | ||
// this system is | // this system is shared with Source Filmmaker, so has support for animating generic properties. | ||
// | // Studiomdl only cares about bones though. | ||
CDmxElement* fromElement; | CDmxElement* fromElement; | ||
CUtlString fromAttribute; | CUtlString fromAttribute; | ||
Line 173: | Line 170: | ||
DmeQuaternionLog log[]; | DmeQuaternionLog log[]; | ||
DmeVector3Log log[]; | DmeVector3Log log[]; | ||
// etc | // etc | ||
}; | }; | ||
Line 215: | Line 212: | ||
DmeMesh* dominators[]; // unknown | DmeMesh* dominators[]; // unknown | ||
DmeMesh* targets[]; // mesh with the shapes on | DmeMesh* targets[]; // mesh with the shapes on | ||
DmeFlexRules* targets[] // | |||
}; | }; | ||
Line 220: | Line 218: | ||
{ | { | ||
CUtlString rawControlNames[]; // which controls are being wrapped | CUtlString rawControlNames[]; // which controls are being wrapped | ||
bool stereo; // equivalent to QC 'split' | bool stereo; // equivalent to QC 'split' | ||
bool eyelid; // flags as an eyelid used by AI for blinking | bool eyelid; // flags as an eyelid used by AI for blinking | ||
float wrinkleScales[]; // wrinklemap stuff; one value for each named control. | float wrinkleScales[]; // wrinklemap stuff; one value for each named control. | ||
float flexMin; | |||
float flexMax; | |||
}; | |||
class DmeVertexDeltaData // a shape | |||
{ | |||
CUtlString vertexFormat[]; // positions, normals, [wrinkle] | |||
bool flipVCoordinates; | |||
bool corrected; | |||
Vector3 positions[]; // offset: (shape position) - (mesh position) | |||
int positionsIndices[]; // index in the main VertexData positions array (*not* positionsIndices) | |||
Vector3 normals[]; // absolute | |||
int normalsIndices[]; // index in the main VertexData normals array (*not* normalsIndices) | |||
float wrinkle[]; // unknown | |||
int wrinkleIndices[]; // unknown | |||
}; | |||
class DmeFlexRules | |||
{ | |||
DmeFlexRule* deltaStates[]; | |||
Vector2 deltaStateWeights[]; | |||
DmeMesh* target; // mesh with the shapes on | |||
}; | |||
class DmeFlexRule | |||
{ | |||
// Name should match the name of a DmeVertexDeltaData element | |||
float result; | |||
CUtlString expression; // +-*/() with min, max & sqrt. | |||
}; | }; | ||
</source> | </source> |
Revision as of 13:08, 7 August 2012
The DMX model format replaces Studiomdl Data. Below is the structure of version 18, which can be compiled by Alien Swarm studiomdl. Source 2009 studiomdl requires version 1.

Common
// A "DAG" is a generic Maya container, appearing here in order to transform objects.
// It can take the place of a DmeMesh, DmeJoint or DmeAttachment at any time.
class DmeDag
{
DmeTransform* transform;
bool visible;
void children[]; // never seen used (Compatibility with DmeModel?)
// One of the following:
CUtlString name // of a DmeJoint
DmeMesh* shape;
DmeAttachment* shape;
};
class DmeJoint // a bone
{
DmeTransform* transform;
void* shape; // only seen empty
bool visible;
DmeJoint children[];
bool lockInfluenceWeights;
};
class DmeTransformList
{
DmeTransform transforms[];
};
class DmeTransform // name is of a defined model if there are children, otherwise blank
{
Vector position;
Quaternion orientation;
};
Mesh
class DmeModelRoot
{
// model and skeleton should point to the same object
DmeModel* model;
DmeModel* skeleton;
};
class DmeModel // one per file
{
DmeTransform* transform; // global model transform...DmeDag not supported here?
void shape; // only seen empty (Compatibility with DmeDag?)
bool visible;
DmeDag / DmeJoint children[]; // mixed type
DmeJoint jointList[];
DmeTransformList baseStates[]; // bone positions; only ever seen with one value
CUtlString upAxis; // uppercase character
};
class DmeAttachment // an attachment
{
bool visible;
bool isRigid; // apparently obsolete?
bool isWorldAligned; // does not move with parent bone, but is still positioned relative to it
};
class DmeMesh
{
bool visible;
void* bindState; // only seen empty
DmeVertexData* currentState; // pointer to default baseState
DmeVertexData baseStates[]; // only ever seen with one value
DmeVertexData deltaStates[]; // flex shapes
DmeFaceSet faceSets[];
Vector2D deltaStateWeights[]; // unknown
Vector2D deltaStateWeightsLagged[]; // unknown
};
class DmeVertexData // mesh data
{
CUtlString vertexFormat[]; // { positions, normals, textureCoordinates, [jointWeights, jointIndices] }
int jointCount; // most bones any one vert is weighted to (should be quite low)
bool flipVCoordinates; // left-handed to right-handed?
// In the next three cases, the first array contains the location of each vertex on the model.
// The second "Indices" array contains one entry one entry per vertex /per face/.
Vector positions[];
int positionsIndices[];
Vector normals[];
int normalsIndices[];
Vector2D textureCoordinates[];
int textureCoordinatesIndices[];
// Weightmapping; optional. The size of BOTH arrays is equal to ( sizeof(positions) * jointCount )
float jointWeights[]; // weight
int jointIndices[]; // index in DmeModel::jointList (v18) or DmeModel::baseStates[0]::transforms (v1)
};
class DmeFaceSet // defines faces, including their material
{
DmeMaterial* material; // the material these faces are drawn with
int faces[]; // the vertices that make up each face, delimited by -1. Quads and n-gons allowed.
};
class DmeMaterial // a material
{
CUtlString mtlName; // with path relative to \game\materials\, no extension
};
Animation
class DmeModelRoot
{
DmeModel* skeleton;
DmeAnimationList* animationList;
};
class DmeAnimationList
{
DmeChannelsClip animations[];
};
class DmeChannelsClip
{
DmeTimeFrame* timeFrame;
Colour color; // SFM only
CUtlString text; // SFM only
bool mute; // SFM only
int frameRate; // typically 30
void trackGroups[]; // SFM only
DmeChannel channels[]; // two for each bone: position and rotation
};
class DmeTimeFrame
{
DmeTime_t start; // no apparent effect, use offset
DmeTime_t duration; // length in seconds...framerate is NOT adjusted
DmeTime_t offset; // remove this many seconds from the start (can be negative)
float scale; // frameRate multiplier
};
class DmeChannel
{
// this system is shared with Source Filmmaker, so has support for animating generic properties.
// Studiomdl only cares about bones though.
CDmxElement* fromElement;
CUtlString fromAttribute;
int fromIndex;
CDmxElement* toElement; // ordinarily a DmeTransform used by the target bone
CUtlString toAttribute;
int toIndex;
int mode; // unknown
// One of:
DmeQuaternionLog log[];
DmeVector3Log log[];
// etc
};
class DmeQuaternionLog // also DmeVector3Log etc.
{
DmeQuaternionLogLayer layers[];
CDmxElement* curveinfo;
bool usedefaultvalue;
Quaternion defaultvalue;
};
class DmeQuaternionLogLayer // also DmeVector3LogLayer etc.
{
// only frames where the bone moves need to be given
// unlike SMD, sparse keyframes are supported
DmeTime_t times[];
int curvetypes[]; // only seen empty...keyframe interp?
Quaternion values[];
};
Flex shapes
class DmeModelRoot
{
// model and skeleton should point to the same object
DmeModel* model;
DmeModel* skeleton;
DmeCombinationOperator* combinationOperator;
};
class DmeCombinationOperator // flex controller global settings
{
DmeCombinationInputControl controls[];
Vector controlValues[]; // rest position...but why a 3D vector?
Vector controlValuesLagged[]; // unknown
bool usesLaggedValues;
DmeMesh* dominators[]; // unknown
DmeMesh* targets[]; // mesh with the shapes on
DmeFlexRules* targets[] //
};
class DmeCombinationInputControl // a flex controller
{
CUtlString rawControlNames[]; // which controls are being wrapped
bool stereo; // equivalent to QC 'split'
bool eyelid; // flags as an eyelid used by AI for blinking
float wrinkleScales[]; // wrinklemap stuff; one value for each named control.
float flexMin;
float flexMax;
};
class DmeVertexDeltaData // a shape
{
CUtlString vertexFormat[]; // positions, normals, [wrinkle]
bool flipVCoordinates;
bool corrected;
Vector3 positions[]; // offset: (shape position) - (mesh position)
int positionsIndices[]; // index in the main VertexData positions array (*not* positionsIndices)
Vector3 normals[]; // absolute
int normalsIndices[]; // index in the main VertexData normals array (*not* normalsIndices)
float wrinkle[]; // unknown
int wrinkleIndices[]; // unknown
};
class DmeFlexRules
{
DmeFlexRule* deltaStates[];
Vector2 deltaStateWeights[];
DmeMesh* target; // mesh with the shapes on
};
class DmeFlexRule
{
// Name should match the name of a DmeVertexDeltaData element
float result;
CUtlString expression; // +-*/() with min, max & sqrt.
};