in Utilities/FlexibleVertexFormat.h [834:1061]
inline uint32_t ComputeFVF(
_In_reads_(maxDeclLength) const D3DVERTEXELEMENT9* pDecl, size_t maxDeclLength)
{
if (!pDecl)
return 0;
if (maxDeclLength > MAXD3DDECLLENGTH + 1)
return 0;
// validate vertex declaration
auto pCurrent = pDecl;
size_t count = 0;
size_t offset = 0;
while (pCurrent->Stream != 0xFF)
{
++count;
if (count > maxDeclLength)
return 0;
if (pCurrent->Stream != 0)
return 0;
if (pCurrent->Type > D3DDECLTYPE_SHORT4)
return 0;
if (offset != pCurrent->Offset)
return 0;
if (pCurrent->Method > D3DDECLMETHOD_LOOKUP)
return 0;
if (((pCurrent->Usage > D3DDECLUSAGE_TEXCOORD)
&& (pCurrent->Usage != D3DDECLUSAGE_POSITIONT)
&& (pCurrent->Usage != D3DDECLUSAGE_COLOR)))
{
return 0;
}
if ((pCurrent->Usage == D3DDECLUSAGE_COLOR) && (pCurrent->UsageIndex > 1))
{
return 0;
}
offset += g_declTypeSizes[pCurrent->Type];
++pCurrent;
}
// Build FVF code
pCurrent = pDecl;
count = 0;
uint32_t fvfCode = 0;
if (pCurrent->Usage == D3DDECLUSAGE_POSITION)
{
if (pCurrent->Type == D3DDECLTYPE_FLOAT3)
{
size_t weights = 0;
++count;
if (count > maxDeclLength)
return 0;
++pCurrent;
if (pCurrent->Usage == D3DDECLUSAGE_BLENDWEIGHT)
{
if ((pCurrent->Type >= D3DDECLTYPE_FLOAT1) && (pCurrent->Type <= D3DDECLTYPE_FLOAT4))
{
weights = pCurrent->Type - D3DDECLTYPE_FLOAT1 + 1;
++count;
if (count > maxDeclLength)
return 0;
++pCurrent;
}
else
{
return 0;
}
}
if (pCurrent->Usage == D3DDECLUSAGE_BLENDINDICES)
{
if (pCurrent->Type == D3DDECLTYPE_UBYTE4)
{
fvfCode |= D3DFVF_LASTBETA_UBYTE4;
++weights;
++count;
if (count > maxDeclLength)
return 0;
++pCurrent;
}
else if (pCurrent->Type == D3DDECLTYPE_D3DCOLOR)
{
fvfCode |= D3DFVF_LASTBETA_D3DCOLOR;
++weights;
++count;
if (count > maxDeclLength)
return 0;
++pCurrent;
}
else
{
return 0;
}
}
switch (weights)
{
case 0: fvfCode |= D3DFVF_XYZ; break;
case 1: fvfCode |= D3DFVF_XYZB1; break;
case 2: fvfCode |= D3DFVF_XYZB2; break;
case 3: fvfCode |= D3DFVF_XYZB3; break;
case 4: fvfCode |= D3DFVF_XYZB4; break;
case 5: fvfCode |= D3DFVF_XYZB5; break;
}
}
else if (pCurrent->Type == D3DDECLTYPE_FLOAT4)
{
fvfCode |= D3DFVF_XYZW;
++count;
if (count > maxDeclLength)
return 0;
++pCurrent;
}
}
else if ((pCurrent->Usage == D3DDECLUSAGE_POSITIONT)
&& (pCurrent->Type == D3DDECLTYPE_FLOAT4))
{
fvfCode |= D3DFVF_XYZRHW;
++count;
if (count > maxDeclLength)
return 0;
++pCurrent;
}
// Normal
if ((pCurrent->Usage == D3DDECLUSAGE_NORMAL)
&& (pCurrent->Type == D3DDECLTYPE_FLOAT3))
{
fvfCode |= D3DFVF_NORMAL;
++count;
if (count > maxDeclLength)
return 0;
++pCurrent;
}
// Point size
if ((pCurrent->Usage == D3DDECLUSAGE_PSIZE)
&& (pCurrent->Type == D3DDECLTYPE_FLOAT1))
{
fvfCode |= D3DFVF_PSIZE;
++count;
if (count > maxDeclLength)
return 0;
++pCurrent;
}
// Diffuse
if ((pCurrent->Usage == D3DDECLUSAGE_COLOR)
&& (pCurrent->UsageIndex == 0)
&& (pCurrent->Type == D3DDECLTYPE_D3DCOLOR))
{
fvfCode |= D3DFVF_DIFFUSE;
++count;
if (count > maxDeclLength)
return 0;
++pCurrent;
}
// Specular
if ((pCurrent->Usage == D3DDECLUSAGE_COLOR)
&& (pCurrent->UsageIndex == 1)
&& (pCurrent->Type == D3DDECLTYPE_D3DCOLOR))
{
fvfCode |= D3DFVF_SPECULAR;
++count;
if (count > maxDeclLength)
return 0;
++pCurrent;
}
// Texture coordinates
size_t i;
for (i = 0; i < 8; ++i)
{
if ((pCurrent->Usage == D3DDECLUSAGE_TEXCOORD)
&& (pCurrent->Type == D3DDECLTYPE_FLOAT1)
&& (pCurrent->UsageIndex == i))
{
fvfCode |= static_cast<uint32_t>(D3DFVF_TEXCOORDSIZE1(i));
}
else if ((pCurrent->Usage == D3DDECLUSAGE_TEXCOORD)
&& (pCurrent->Type == D3DDECLTYPE_FLOAT2)
&& (pCurrent->UsageIndex == i))
{
fvfCode |= static_cast<uint32_t>(D3DFVF_TEXCOORDSIZE2(i));
}
else if ((pCurrent->Usage == D3DDECLUSAGE_TEXCOORD)
&& (pCurrent->Type == D3DDECLTYPE_FLOAT3)
&& (pCurrent->UsageIndex == i))
{
fvfCode |= static_cast<uint32_t>(D3DFVF_TEXCOORDSIZE3(i));
}
else if ((pCurrent->Usage == D3DDECLUSAGE_TEXCOORD)
&& (pCurrent->Type == D3DDECLTYPE_FLOAT4)
&& (pCurrent->UsageIndex == i))
{
fvfCode |= static_cast<uint32_t>(D3DFVF_TEXCOORDSIZE4(i));
}
else
break;
++count;
if (count > maxDeclLength)
return 0;
++pCurrent;
}
fvfCode |= static_cast<uint32_t>(i << D3DFVF_TEXCOUNT_SHIFT);
if (pCurrent->Stream != 0xff)
{
return 0;
}
return fvfCode;
}