DMX model

From Valve Developer Community
Revision as of 13:37, 19 January 2011 by TomEdwards (talk | contribs) (corrections)
Jump to navigation Jump to search

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.

Note.pngNote:All names are case sensitive.
class DmeModelRoot
{
	// model and skeleton should point to the same object
	DmeModel*	model;
	DmeModel*	skeleton;
	
	DmeCombinationOperator*	combinationOperator; // flex animations only
};

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
};

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.
};

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
};

// 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;
};

class DmeAttachment // an attachment
{
	bool		visible;
	bool		IsRigid; // does not animate with associated bone
	bool		isWorldAligned; // transform in world co-ords
};

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[];	// unknown
	
	DmeFaceSet			faceSets[];

	Vector2D			deltaStateWeights[];		// unknown
	Vector2D			deltaStateWeightsLagged[];	// unknown
};

class DmeVertexData // mesh data
{
	CUtlString	vertexFormat[];		// positions, normals, textureCoordinates, [jointWeights, jointIndices]
	int			jointCount;			// total number of bones this mesh is weighted to
	bool		flipVCoordinates;	// left-handed to right-handed?

	// In the next three cases, the "Indicies" array contains one entry for each vertex.
	// the indice value defines which value from the 'real' array the vertex takes. In this
	// way, vertices can share data. This is a useful optimisation since each poly has its
	// own three verts, even if they overlap other verts.
	
	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 );
	// it is not possible for two verts in the same place to be weighted differently.
	float		jointWeights[];		// weight
	int			jointIndicies[];	// index in DmeModel::jointList
};

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
};