In|Framez® Papers

Flexible-Vertex-Format (FVF) Cracker Source


During the development of DirectSkeleton® (a Direct3D Engine), I had a situation where I had two 3D meshes that need to be LERPed (animated). The trick was that the meshes didn't have a constant vertex definition. The artists might send meshes with color data included within the vertex definition itself, meshes that contain different number of texture coordinates sets, etc...
The only thing that I have in hand is a Flexible-Vertex-Format (FVF) code that describes the vertex definition of each mesh. Through this little piece of info, I had to know where lies the vertex's Diffuse,Normal..etc inside the mesh's vertex structure.
And so, here it is. The function GetFVFComponentOffset will do this piece of magic :


GetFVFComponentOffset

Returns the offset (in bytes) of a vertex component within the structure that resembles its Flexible-Vertex-Format (FVF) code.

DWORD GetFVFComponentOffset(
  DWORD dwFVF,
  DWORD dwFVFComponent,
  BYTE iTexCoordIndex
);

Parameters

dwFVF
[in] A valid FVF code that expresses the whole vertex structure.
dwFVFComponent
[in] The FVF Code of the component that you want to recieve its offset inside the vertex structure.
Pass single codes only. Combined codes are invalid and might fail or return undefined results. Also, the following FVF flags are invalid :
Also, dwFVFComponent must be part of (or equal) dwFVF. It is safe to use the D3DFVF_TEXCOORDSIZEn set of macros to construct Texture Coordinate Sets FVF codes and pass them to dwFVFComponent.
iTexCoordIndex
[in] The index of the requested Texture Coordinates Set. If dwFVFComponent is a Texture Coordinates Set FVF, then this parameter must be set to the same index passed to the D3DFVF_TEXCOORDSIZEn macro used to build dwFVFComponent. If dwFVFComponent is not a Texture Coordinates Set FVF, then this parameter is ignored.

Return Values

The offset (in bytes) of the requested component inside the vertex structure.
If one of the parameters were invalid, or dwFVFComponent is not part of dwFVF, then the function fails and the return value is 0xFFFFFFFF.

Remarks

The following code snippets show how the function can be used :

Example 1 :

// Define the FVF
DWORD anFVF = D3DFVF_XYZ|D3DFVF_NORMAL|D3DFVF_DIFFUSE;
DWORD Offset = 0;
Offset = GetFVFComponentOffset(anFVF,D3DFVF_XYZ);	// Returns 0
Offset = GetFVFComponentOffset(anFVF,D3DFVF_NORMAL);	// Returns 12
Offset = GetFVFComponentOffset(anFVF,D3DFVF_DIFFUSE);	// Returns 24

BYTE *pVertexData;
// Lock the Vertex Buffer and save pointer to the data in pVertexData
// With Offset containing the offset ot the Diffuse component, we'll
// manipulate the first vertex's Diffuse
pVertexData += Offset;	// Move to Diffuse
*(DWORD*)pVertexData = D3DCOLOR_ARGB(255,255,0,0);	// Opaque Red Vertex

Example 2 :
struct CUSTOMVERTEX
{
	float x,y,z,rhw;	// Transformed Position (16 Bytes)
	floay nx,ny,nz;	// Normal (12 Bytes)
	float u,v;	// 2D Texture Coordinates (8 Bytes)
};

// Define FVF for CUSTOMVERTEX
DWORD anFVF = D3DFVF_XYZRHW|D3DFVF_NORMAL|D3DFVF_TEX1|D3DFVF_TEXCOORDSIZE2(0);
DWORD Offset = 0;
Offset = GetFVFComponentOffset(anFVF,D3DFVF_XYZRHW);			// Returns 0
Offset = GetFVFComponentOffset(anFVF,D3DFVF_NORMAL);			// Returns 16
Offset = GetFVFComponentOffset(anFVF,D3DFVF_DIFFUSE);			// Returns 0xFFFFFFFF (Failed)
Offset = GetFVFComponentOffset(anFVF,D3DFVF_TEXCOORDSIZE2(0),0);	// Returns 28

Example 3 :
struct CUSTOMVERTEX
{
	float x,y,z;	// Untransformed Position (12 Bytes)
	float b1;		// One Blending Weight (4 Bytes)
	float u3,v3,z3;	// 3D Texture Coordinates (12 Bytes)
	float u1;		// 1D Texture Coordinates (4 Bytes)
	float u2,v2;	// 2D Texture Coordinates (8 Bytes)
	float u4,v4,w4,t4;	// 4D Texture Coordinates (16 Bytes)
};

// Define FVF for CUSTOMVERTEX
DWORD anFVF = D3DFVF_XYZB1|D3DFVF_TEX4|	/* 4 Texture Coordinates Sets */
	     D3DFVF_TEXCOORDSIZE3(0)|	/* 3D Set */
	     D3DFVF_TEXCOORDSIZE1(1)|	/* 1D Set */
	     D3DFVF_TEXCOORDSIZE2(2)|	/* 2D Set */
	     D3DFVF_TEXCOORDSIZE4(3);	/* 4D Set */
DWORD Offset = 0;
Offset = GetFVFComponentOffset(anFVF,D3DFVF_XYZ);			// Returns 0xFFFFFFFF (Failed)
Offset = GetFVFComponentOffset(anFVF,D3DFVF_XYZB1);			// Returns 0
Offset = GetFVFComponentOffset(anFVF,D3DFVF_TEXCOORDSIZE3(0),0);	// Returns 16
Offset = GetFVFComponentOffset(anFVF,D3DFVF_TEXCOORDSIZE1(1),1);	// Returns 28
Offset = GetFVFComponentOffset(anFVF,D3DFVF_TEXCOORDSIZE2(2),2);	// Returns 32
Offset = GetFVFComponentOffset(anFVF,D3DFVF_TEXCOORDSIZE4(3),3);	// Returns 40

// This will return an error, because there is no 3D Set defined at index 1
Offset = GetFVFComponentOffset(anFVF,D3DFVF_TEXCOORDSIZE3(1),1);	// Returns 0xFFFFFFFF (Failed)


Example 4 :
struct CUSTOMVERTEX
{
	float x,y,z;	// Untransformed Position (12 Bytes)
	float b1,b2;	// Two Blending Weights (8 Bytes)
	float u1,v1;	// 2D Texture Coordinates (8 Bytes)
	float u2,v2;	// 2D Texture Coordinates (8 Bytes)
	float u3,v3;	// 2D Texture Coordinates (8 Bytes)
};

// Define FVF for CUSTOMVERTEX
DWORD anFVF = D3DFVF_XYZB2|D3DFVF_TEX3|	/* 3 Texture Coordinates Sets */
	     D3DFVF_TEXCOORDSIZE2(0)|	/* 2D Set */
	     D3DFVF_TEXCOORDSIZE2(1)|	/* 2D Set */
	     D3DFVF_TEXCOORDSIZE2(2);	/* 2D Set */
DWORD Offset = 0;
Offset = GetFVFComponentOffset(anFVF,D3DFVF_XYZB1);			// Returns 0xFFFFFFFF (Failed)
Offset = GetFVFComponentOffset(anFVF,D3DFVF_XYZB2);			// Returns 0
Offset = GetFVFComponentOffset(anFVF,D3DFVF_TEXCOORDSIZE2(0),0);	// Returns 20
Offset = GetFVFComponentOffset(anFVF,D3DFVF_TEXCOORDSIZE2(1),1);	// Returns 28
Offset = GetFVFComponentOffset(anFVF,D3DFVF_TEXCOORDSIZE2(2),2);	// Returns 36

// This will return an error, because there is no 1D Set defined at index 0
Offset = GetFVFComponentOffset(anFVF,D3DFVF_TEXCOORDSIZE1(0),0);	// Returns 0xFFFFFFFF (Failed)


Requirements

See Also:

Download Flexible-Vertex-Format (FVF) Cracker Source.


A word from the author:

A big part of the code has been taken from The MSDN Shader Workshop Application by Philip Taylor from Microsoft Corporation. Thanks for Philip and all the other Microsoft guys related to this great column.
Please send comments, bugs and suggestions to this address.