DMX model: Difference between revisions

From Valve Developer Community
Jump to navigation Jump to search
No edit summary
No edit summary
Line 7: Line 7:
== Versions ==
== Versions ==


;1
; 1
: Source 2007
: Source 2007
: Source 2009
: Source 2009
Line 20: Line 20:
: CS:GO
: CS:GO


== Common ==
== Layout ==
 
=== Common ===


<source lang=cpp>
<source lang=cpp>
Line 58: Line 60:
</source>
</source>


== Mesh ==
=== Mesh ===


<source lang=cpp>
<source lang=cpp>
Line 75: Line 77:
void shape; // only seen empty (Compatibility with DmeDag?)
void shape; // only seen empty (Compatibility with DmeDag?)
bool visible;
bool visible;
DmeDag|DmeJoint children[]; // mixed type
DmeDag|DmeJoint children[]; // mixed type, contains DmeMesh elements too
DmeJoint jointList[];
DmeJoint jointList[];
DmeTransformList baseStates[]; // bone positions; only ever seen with one value
DmeTransformList baseStates[]; // bone positions; only ever seen with one value
Line 122: Line 124:
// 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 (v15+) or DmeModel::jointTransforms (v1-14)


float balance[]; // Defines flex controller stereo split. 0 means right, 1 means left.
float balance[]; // Defines flex controller stereo split. 0 means right, 1 means left.
Line 158: Line 160:
</source>
</source>


=== Flex controllers ===
==== Flex controllers ====


<source lang=cpp>
<source lang=cpp>
Line 207: Line 209:
</source>
</source>


== Animation ==
=== Animation ===


<source lang=cpp>
<source lang=cpp>
Line 280: Line 282:
};
};
</source>
</source>
== Changes ==
This list will inevitably be incomplete.
=== 18 ===
; <code>DmeTimeFrame</code>
: Introduction of <code>DmeTime</code> attribute type.
=== 15 ===
; <code>DmeModel</code>
: Replaced "jointTransforms" with "jointList"
; <code>DmeTimeFrame</code>
: Renamed "durationTime" to "duration"
: Renamed "offsetTime" to "offset"


[[Category:Modeling]]
[[Category:Modeling]]
[[Category:Technical]]
[[Category:Technical]]
[[Category:File formats]]
[[Category:File formats]]

Revision as of 11:03, 6 November 2012

The DMX model format replaces Studiomdl Data. This article describes version 18.

Note.pngNote:All names are case sensitive.

Versions

1
Source 2007
Source 2009
15
Left 4 Dead
Left 4 Dead 2
18 (documented below)
Alien Swarm
Source MP
Portal 2
Source Filmmaker
CS:GO

Layout

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;

	DmeCombinationOperator	combinationOperator; // flex controllers; optional
};

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, contains DmeMesh elements too
	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	
	DmeVertexDeltaData	deltaStates[];	// flex shapes	
	DmeFaceSet			faceSets[];

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

class DmeVertexData // mesh data
{
	CUtlString	vertexFormat[];		// { positions, normals, textureCoordinates, [jointWeights, jointIndices, balance] }
	int			jointCount;			// most bones any one vert is weighted to; max 3
	bool		flipVCoordinates;	// left-handed to right-handed?

	// 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 (v15+) or DmeModel::jointTransforms (v1-14)

	float		balance[];			// Defines flex controller stereo split. 0 means right, 1 means left.
	int			balanceIndices[];
};

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

class DmeVertexDeltaData // a shape key
{
	CUtlString	vertexFormat[]; // positions, normals, [wrinkle]
	bool		flipVCoordinates; // unknown
	bool		corrected; // unknown

	// these arrays use the same system as those in DmeVertexData

	Vector3		positions[]; // offset: (shape position) - (mesh position)
	int			positionsIndices[]; // index in VertexData::positions

	Vector3		normals[]; // absolute
	int			normalsIndices[]; // index in VertexData::normals

	float		wrinkle[]; // Multiplier for controller-defined wrinkle weight
	int			wrinkleIndices[]; // index in VertexData::positions
};

Flex controllers

class DmeCombinationOperator // flex controller global settings
{
	DmeCombinationInputControl		controls[];
	Vector							controlValues[];		// rest position...but why a 3D vector?
	Vector							controlValuesLagged[];	// unknown
	bool							usesLaggedValues;
	DmeCombinationDominationRule	dominators[];
	DmeMesh|DmeFlexRules			targets[];			// mixed type
};

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 strength for each named control. Positive means compress, negative means stretch.
	float		flexMin;
	float		flexMax;
};

class DmeCombinationDominationRule // Disables certain shapes (NOT controllers) when others are active
{
	CUtlString	dominators[];
	CUtlString	supressed[];
};

class DmeFlexRules // shape key pre-processing
{
	DmeFlexRule|DmeFlexRulePassThrough	deltaStates[]; // mixed type
	Vector2								deltaStateWeights[];
	DmeMesh								target; // mesh with the shapes on
};

// In the next two cases, the element name must match
// the name of a DmeVertexDeltaData element on the target DmeMesh
class DmeFlexRule
{
	float		result;
	CUtlString	expression; // +-/() with min, max & sqrt.
};
class DmeFlexRulePassThrough // no expression required
{
	float		result;
};

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 format 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[];
};

Changes

This list will inevitably be incomplete.

18

DmeTimeFrame
Introduction of DmeTime attribute type.

15

DmeModel
Replaced "jointTransforms" with "jointList"
DmeTimeFrame
Renamed "durationTime" to "duration"
Renamed "offsetTime" to "offset"