Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

1021 lines
34 KiB

#include "pch.cpp"
#pragma hdrstop
const D3DVALUE __HUGE_PWR2 = 1024.0f*1024.0f*2.0f;
//---------------------------------------------------------------------
// This function should be called every time FVF ID is changed
// All pv flags, input and output FVF id should be set before calling the
// function.
//---------------------------------------------------------------------
void UpdateComponentOffsets (DWORD dwFVFIn,
LPDWORD pNormalOffset,
LPDWORD pDiffOffset,
LPDWORD pSpecOffset,
LPDWORD pTexOffset)
{
DWORD dwOffset = 0;
switch( dwFVFIn & D3DFVF_POSITION_MASK )
{
case D3DFVF_XYZ:
dwOffset = sizeof(D3DVECTOR);
break;
case D3DFVF_XYZB1:
dwOffset = sizeof(D3DVECTOR) + sizeof(D3DVALUE);
break;
case D3DFVF_XYZB2:
dwOffset = sizeof(D3DVECTOR) + 2*sizeof(D3DVALUE);
break;
case D3DFVF_XYZB3:
dwOffset = sizeof(D3DVECTOR) + 3*sizeof(D3DVALUE);
break;
case D3DFVF_XYZB4:
dwOffset = sizeof(D3DVECTOR) + 4*sizeof(D3DVALUE);
break;
case D3DFVF_XYZB5:
dwOffset = sizeof(D3DVECTOR) + 5*sizeof(D3DVALUE);
break;
default:
DPFM(0,TNL,("Unable to compute offsets, strange FVF bits set"));
}
*pNormalOffset = dwOffset;
if (dwFVFIn & D3DFVF_NORMAL)
dwOffset += sizeof(D3DVECTOR);
if (dwFVFIn & D3DFVF_RESERVED1)
dwOffset += sizeof(D3DVALUE);
// Offset to the diffuse color
*pDiffOffset = dwOffset;
if (dwFVFIn & D3DFVF_DIFFUSE)
dwOffset += sizeof(DWORD);
// Offset to the specular color
*pSpecOffset = dwOffset;
if (dwFVFIn & D3DFVF_SPECULAR)
dwOffset += sizeof(DWORD);
// Offset to the texture data
*pTexOffset = dwOffset;
}
//---------------------------------------------------------------------
// SetupFVFData:
// Compute Output FVF and the size of output vertices
//---------------------------------------------------------------------
void
RRProcessVertices::SetupFVFData(BOOL bFogEnabled, BOOL bSpecularEnabled)
{
// Compute number of texture coordinates
m_dwNumTexCoords = FVF_TEXCOORD_NUMBER(m_dwFVFIn);
// Compute output FVF
m_qwFVFOut = D3DFVF_XYZRHW;
// If normal is present we have to compute specular and diffuse
// Otherwise set these bits the same as input.
// Not that normal should not be present for XYZRHW position type
if (m_dwTLState & RRPV_DOLIGHTING)
{
m_qwFVFOut |= D3DFVF_DIFFUSE | D3DFVF_SPECULAR;
}
else
{
m_qwFVFOut |= (m_dwFVFIn & (D3DFVF_DIFFUSE | D3DFVF_SPECULAR));
}
// Always set specular flag if fog is enabled
// if (this->rstates[D3DRENDERSTATE_FOGENABLE])
if (bFogEnabled)
{
m_qwFVFOut |= D3DFVF_SPECULAR;
}
// Clear specular flag if specular disabled
// else if (!this->rstates[D3DRENDERSTATE_SPECULARENABLE])
else if (!bSpecularEnabled && !(m_dwFVFIn & D3DFVF_SPECULAR))
{
m_qwFVFOut &= ~D3DFVF_SPECULAR;
}
#ifdef __POINTSPRITES
// Reserve space for point size, if needed
if (m_dwTLState & RRPV_DOCOMPUTEPOINTSIZE)
{
m_qwFVFOut |= D3DFVF_S;
}
#endif
// Reserve space for eye space info, if needed
if (m_dwTLState & RRPV_DOPASSEYENORMAL)
{
m_qwFVFOut |= D3DFVFP_EYENORMAL;
}
if (m_dwTLState & RRPV_DOPASSEYEXYZ)
{
m_qwFVFOut |= D3DFVFP_EYEXYZ;
}
// Set up number of texture coordinates and copy texture formats
m_qwFVFOut |= (m_dwNumTexCoords << D3DFVF_TEXCOUNT_SHIFT) |
(m_dwFVFIn & 0xFFFF0000);
// Compute size of texture coordinates
// This size is the same for input and output FVFs,
// because for DX7 drivers they have number of texture and texture formats
m_dwTextureCoordSizeTotal = 0;
ComputeTextureCoordSize(m_dwFVFIn, m_dwTexCoordSize,
&m_dwTextureCoordSizeTotal);
// Compute output size
m_dwOutputVtxSize = GetFVFVertexSize( m_qwFVFOut );
m_position.dwStride = GetFVFVertexSize( m_dwFVFIn );
// Now compute the input FVF dependent offsets used by the Geometry loop
UpdateComponentOffsets (m_dwFVFIn, &m_dwNormalOffset,
&m_dwDiffuseOffset, &m_dwSpecularOffset,
&m_dwTexOffset);
return;
}
///////////////////////////////////////////////////////////////////////////////
// SavePrimitiveData
///////////////////////////////////////////////////////////////////////////////
void
ReferenceRasterizer::SavePrimitiveData(
DWORD dwFVFIn,
LPVOID pVtx,
UINT cVertices,
D3DPRIMITIVETYPE PrimType
)
{
//
// 1) Save the incoming information
//
m_primType = PrimType;
m_position.lpvData = pVtx;
// Force some state changes if the FVF is different
if( dwFVFIn != m_dwFVFIn )
{
m_dwDirtyFlags |= RRPV_DIRTY_COLORVTX;
}
m_dwFVFIn = dwFVFIn;
m_dwNumVertices = cVertices;
// No indices to work with
m_dwNumIndices = 0;
m_pIndices = NULL;
}
void
ReferenceRasterizer::SavePrimitiveData(
DWORD dwFVFIn,
LPVOID pVtx,
UINT cVertices,
D3DPRIMITIVETYPE PrimType,
LPWORD pIndices,
UINT cIndices
)
{
//
// 1) Save the incoming information
//
m_primType = PrimType;
m_position.lpvData = pVtx;
// Force some state changes if the FVF is different
if( dwFVFIn != m_dwFVFIn )
{
m_dwDirtyFlags |= RRPV_DIRTY_COLORVTX;
}
m_dwFVFIn = dwFVFIn;
m_dwNumVertices = cVertices;
m_dwNumIndices = cIndices;
m_pIndices = pIndices;
}
///////////////////////////////////////////////////////////////////////////////
// Process primitives implementation:
// 1) Compute FVF info
// 2) Grow buffers to the requisite size
// 3) Initialize clipping state
// 4) Update T&L state
// 5) Transform, Light and compute clipping for vertices
// 6) Clip and Draw the primitives
//
///////////////////////////////////////////////////////////////////////////////
HRESULT
ReferenceRasterizer::ProcessPrimitive(
BOOL bIndexedPrim
)
{
HRESULT ret = D3D_OK;
DWORD dwVertexPoolSize = 0;
//
// Update T&L state (must be before FVFData is set up)
//
// Update Lighting and related state and flags
if ((ret = UpdateTLState()) != D3D_OK)
return ret;
//
// Compute Output FVF and the size of output vertices
//
SetupFVFData(GetRenderState()[D3DRENDERSTATE_FOGENABLE],
GetRenderState()[D3DRENDERSTATE_SPECULARENABLE]);
//
// Clipping information depends both on the output FVF computation
// and the other State, so do it here after both have been computed
//
if (m_dwTLState & RRPV_DOCLIPPING)
{
// Figure out which pieces need to be interpolated in new vertices.
m_clipping.dwInterpolate = 0;
if (GetRenderState()[D3DRENDERSTATE_SHADEMODE] == D3DSHADE_GOURAUD)
{
m_clipping.dwInterpolate |= RRCLIP_INTERPOLATE_COLOR;
if (m_qwFVFOut & D3DFVF_SPECULAR)
{
m_clipping.dwInterpolate |= RRCLIP_INTERPOLATE_SPECULAR;
}
}
if (GetRenderState()[D3DRENDERSTATE_FOGENABLE])
{
m_clipping.dwInterpolate |= RRCLIP_INTERPOLATE_SPECULAR;
}
if (FVF_TEXCOORD_NUMBER(m_dwFVFIn) != 0)
{
m_clipping.dwInterpolate |= RRCLIP_INTERPOLATE_TEXTURE;
}
if (m_dwTLState & RRPV_DOCOMPUTEPOINTSIZE)
{
m_clipping.dwInterpolate |= RRCLIP_INTERPOLATE_S;
}
if (m_dwTLState & RRPV_DOPASSEYENORMAL)
{
m_clipping.dwInterpolate |= RRCLIP_INTERPOLATE_EYENORMAL;
}
if (m_dwTLState & RRPV_DOPASSEYEXYZ)
{
m_clipping.dwInterpolate |= RRCLIP_INTERPOLATE_EYEXYZ;
}
// Clear clip union and intersection flags
m_clipIntersection = 0;
m_clipUnion = 0;
HRESULT hr = S_OK;
HR_RET( UpdateClippingData( GetRenderState()[D3DRENDERSTATE_CLIPPLANEENABLE] ));
}
// This needs to be updated bbecause the rasterizer part of
// the Reference Driver uses it.
m_qwFVFControl = m_qwFVFOut;
//
// Grow buffers to the requisite size
//
// Size of the buffer required to transform into
dwVertexPoolSize = m_dwNumVertices * m_dwOutputVtxSize;
// Grow TLVBuf if required
if (dwVertexPoolSize > this->m_TLVBuf.GetSize())
{
if (this->m_TLVBuf.Grow(dwVertexPoolSize) != D3D_OK)
{
DPFM(0,TNL,("Could not grow TL vertex buffer"));
ret = DDERR_OUTOFMEMORY;
return ret;
}
}
this->m_pvOut = this->m_TLVBuf.GetAddress();
// Grow ClipFlagBuf if required
if (GetRenderState()[D3DRENDERSTATE_CLIPPING])
{
DWORD size = m_dwNumVertices * sizeof(RRCLIPCODE);
if (size > this->m_ClipFlagBuf.GetSize())
{
if (this->m_ClipFlagBuf.Grow(size) != D3D_OK)
{
DPFM(0,TNL,("Could not grow clip buffer"));
ret = DDERR_OUTOFMEMORY;
return ret;
}
}
this->m_pClipBuf = (RRCLIPCODE *)this->m_ClipFlagBuf.GetAddress();
}
//
// Transform, Light and compute clipping for vertices
//
if (ProcessVertices())
{
// If the entire primitive lies outside the view frustum, quit
// without drawing
return D3D_OK;
}
//
// Clip and Draw the primitives
//
if (bIndexedPrim)
{
if (!NeedClipping((m_dwTLState & RRPV_GUARDBAND), m_clipUnion))
{
ret = DoDrawOneIndexedPrimitive( this,
m_dwOutputVtxSize,
(PUINT8) m_pvOut,
m_pIndices,
m_primType,
m_dwNumIndices
);
}
else
{
ret = DrawOneClippedIndexedPrimitive();
}
}
else
{
if (!NeedClipping((m_dwTLState & RRPV_GUARDBAND), m_clipUnion))
{
ret = DoDrawOnePrimitive( this,
m_dwOutputVtxSize,
(PUINT8) m_pvOut,
m_primType,
m_dwNumVertices
);
}
else
{
ret = DrawOneClippedPrimitive();
}
}
#if 0
D3DFE_UpdateClipStatus(this);
#endif //0
return ret;
}
//---------------------------------------------------------------------
// ReferenceRasterizer::UpdateTLState
// Updates transform and lighting related state
//---------------------------------------------------------------------
HRESULT
ReferenceRasterizer::UpdateTLState()
{
HRESULT hr = D3D_OK;
//
// Update Geometry Loop flags based on the current state set
//
// Need to compute the Min of what is in the FVF and the renderstate.
m_numVertexBlends = min( GetRenderState()[D3DRENDERSTATE_VERTEXBLEND],
((m_dwFVFIn & D3DFVF_POSITION_MASK) >> 1) - 2 );
#ifdef __POINTSPRITES
//
// Check prim type to see if point size computation is needed
// Need to set this before the transform state is set
//
m_dwTLState &= ~RRPV_DOCOMPUTEPOINTSIZE;
switch(m_primType)
{
case D3DPT_POINTLIST:
m_dwTLState |= RRPV_DOCOMPUTEPOINTSIZE;
break;
}
#endif
m_dwTLState &= ~(RRPV_DOPASSEYENORMAL|RRPV_DOPASSEYEXYZ);
for ( DWORD dwStage=0; dwStage<D3DHAL_TSS_MAXSTAGES; dwStage++ )
{
// check for disabled stage (subsequent are thus inactive)
if ( GetTextureStageState(dwStage)[D3DTSS_COLOROP] == D3DTOP_DISABLE )
{
break;
}
switch ( GetTextureStageState(dwStage)[D3DTSS_TEXCOORDINDEX] & 0xffff0000)
{
case D3DTSS_TCI_CAMERASPACENORMAL:
m_dwTLState |= RRPV_DOPASSEYENORMAL;
break;
case D3DTSS_TCI_CAMERASPACEPOSITION:
m_dwTLState |= RRPV_DOPASSEYEXYZ;
break;
case D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR:
m_dwTLState |= (RRPV_DOPASSEYENORMAL|RRPV_DOPASSEYEXYZ);
break;
}
}
// Fog or not:
// Compute fog if: 1) Fogging is enabled
// 2) VertexFog mode is not FOG_NONE
// 3) TableFog mode is FOG_NONE
// If both table and vertex fog are not FOG_NONE, table fog
// is applied.
if (GetRenderState()[D3DRENDERSTATE_FOGENABLE] &&
GetRenderState()[D3DRENDERSTATE_FOGVERTEXMODE] &&
!GetRenderState()[D3DRENDERSTATE_FOGTABLEMODE])
{
m_dwTLState |= RRPV_DOFOG;
// Range Fog
if (GetRenderState()[D3DRENDERSTATE_RANGEFOGENABLE])
{
m_dwTLState |= RRPV_RANGEFOG;
}
else
{
m_dwTLState &= ~RRPV_RANGEFOG;
}
}
else
{
m_dwTLState &= ~(RRPV_DOFOG | RRPV_RANGEFOG);
}
// Something changed in the transformation state
// Recompute digested transform state
HR_RET(UpdateXformData());
// Something changed in the lighting state
if ((m_dwTLState & RRPV_DOLIGHTING) &&
(m_dwDirtyFlags & RRPV_DIRTY_LIGHTING))
{
//
// Compute Colorvertex flags only if the lighting is enabled
//
m_dwTLState &= ~RRPV_COLORVERTEXFLAGS;
m_lighting.pAmbientSrc = &m_lighting.matAmb;
m_lighting.pDiffuseSrc = &m_lighting.matDiff;
m_lighting.pSpecularSrc = &m_lighting.matSpec;
m_lighting.pEmissiveSrc = &m_lighting.matEmis;
m_lighting.pDiffuseAlphaSrc = &m_lighting.materialDiffAlpha;
m_lighting.pSpecularAlphaSrc = &m_lighting.materialSpecAlpha;
if (GetRenderState()[D3DRENDERSTATE_COLORVERTEX])
{
switch( GetRenderState()[D3DRENDERSTATE_AMBIENTMATERIALSOURCE] )
{
case D3DMCS_MATERIAL:
break;
case D3DMCS_COLOR1:
{
if (m_dwFVFIn & D3DFVF_DIFFUSE)
{
m_dwTLState |=
(RRPV_VERTEXDIFFUSENEEDED | RRPV_COLORVERTEXAMB);
m_lighting.pAmbientSrc = &m_lighting.vertexDiffuse;
}
}
break;
case D3DMCS_COLOR2:
{
if (m_dwFVFIn & D3DFVF_SPECULAR)
{
m_dwTLState |=
(RRPV_VERTEXSPECULARNEEDED | RRPV_COLORVERTEXAMB);
m_lighting.pAmbientSrc = &m_lighting.vertexSpecular;
}
}
break;
}
switch( GetRenderState()[D3DRENDERSTATE_DIFFUSEMATERIALSOURCE] )
{
case D3DMCS_MATERIAL:
break;
case D3DMCS_COLOR1:
{
if (m_dwFVFIn & D3DFVF_DIFFUSE)
{
m_dwTLState |=
(RRPV_VERTEXDIFFUSENEEDED | RRPV_COLORVERTEXDIFF);
m_lighting.pDiffuseSrc = &m_lighting.vertexDiffuse;
m_lighting.pDiffuseAlphaSrc =
&m_lighting.vertexDiffAlpha;
}
}
break;
case D3DMCS_COLOR2:
{
if (m_dwFVFIn & D3DFVF_SPECULAR)
{
m_dwTLState |=
(RRPV_VERTEXSPECULARNEEDED | RRPV_COLORVERTEXDIFF);
m_lighting.pDiffuseSrc = &m_lighting.vertexSpecular;
m_lighting.pDiffuseAlphaSrc =
&m_lighting.vertexSpecAlpha;
}
}
break;
}
switch( GetRenderState()[D3DRENDERSTATE_SPECULARMATERIALSOURCE] )
{
case D3DMCS_MATERIAL:
break;
case D3DMCS_COLOR1:
{
if (m_dwFVFIn & D3DFVF_DIFFUSE)
{
m_dwTLState |=
(RRPV_VERTEXDIFFUSENEEDED | RRPV_COLORVERTEXSPEC);
m_lighting.pSpecularSrc = &m_lighting.vertexDiffuse;
m_lighting.pSpecularAlphaSrc =
&m_lighting.vertexDiffAlpha;
}
}
break;
case D3DMCS_COLOR2:
{
if (m_dwFVFIn & D3DFVF_SPECULAR)
{
m_dwTLState |=
(RRPV_VERTEXSPECULARNEEDED | RRPV_COLORVERTEXSPEC);
m_lighting.pSpecularSrc = &m_lighting.vertexSpecular;
m_lighting.pSpecularAlphaSrc =
&m_lighting.vertexSpecAlpha;
}
}
break;
}
switch( GetRenderState()[D3DRENDERSTATE_EMISSIVEMATERIALSOURCE] )
{
case D3DMCS_MATERIAL:
break;
case D3DMCS_COLOR1:
{
if (m_dwFVFIn & D3DFVF_DIFFUSE)
{
m_dwTLState |=
(RRPV_VERTEXDIFFUSENEEDED | RRPV_COLORVERTEXEMIS);
m_lighting.pEmissiveSrc = &m_lighting.vertexDiffuse;
}
}
break;
case D3DMCS_COLOR2:
{
if (m_dwFVFIn & D3DFVF_SPECULAR)
{
m_dwTLState |=
(RRPV_VERTEXSPECULARNEEDED | RRPV_COLORVERTEXEMIS);
m_lighting.pEmissiveSrc = &m_lighting.vertexSpecular;
}
}
break;
}
}
// If specular is needed in the output and has been provided
// in the input, force the copy of specular data
if ((m_dwFVFIn & D3DFVF_SPECULAR) &&
(GetRenderState()[D3DRENDERSTATE_SPECULARENABLE] == FALSE))
{
m_dwTLState |= RRPV_VERTEXSPECULARNEEDED;
}
//
// Update the remaining light state
//
HR_RET(UpdateLightingData());
}
if ((m_dwTLState & RRPV_DOFOG) &&
(m_dwDirtyFlags & RRPV_DIRTY_FOG))
{
HR_RET(UpdateFogData());
}
return hr;
}
///////////////////////////////////////////////////////////////////////////////
// RRProcessVertices method implementations
///////////////////////////////////////////////////////////////////////////////
//---------------------------------------------------------------------
inline void MakeRRCOLOR( RRCOLOR *out, DWORD inputColor )
{
out->r = (D3DVALUE)RGBA_GETRED( inputColor );
out->g = (D3DVALUE)RGBA_GETGREEN( inputColor );
out->b = (D3DVALUE)RGBA_GETBLUE( inputColor );
}
//---------------------------------------------------------------------
// RRProcessVertices::ComputeClipCodes
//---------------------------------------------------------------------
RRCLIPCODE
RRProcessVertices::ComputeClipCodes(RRCLIPCODE* pclipIntersection, RRCLIPCODE* pclipUnion,
FLOAT x_clip, FLOAT y_clip, FLOAT z_clip, FLOAT w_clip, FLOAT fPointSize)
{
// if true, need to deal with point size for clipping
BOOL bPointSize = (fPointSize > 1.0f);
D3DVALUE xx = w_clip - x_clip;
D3DVALUE yy = w_clip - y_clip;
D3DVALUE zz = w_clip - z_clip;
// if (x < 0) clip |= RRCLIP_LEFTBIT;
// if (x >= we) clip |= RRCLIP_RIGHTBIT;
// if (y < 0) clip |= RRCLIP_BOTTOMBIT;
// if (y >= we) clip |= RRCLIP_TOPBIT;
// if (z < 0) clip |= RRCLIP_FRONTBIT;
// if (z >= we) clip |= RRCLIP_BACKBIT;
RRCLIPCODE clip = ((AS_INT32(x_clip) & 0x80000000) >> (32-RRCLIP_LEFTBIT)) |
((AS_INT32(y_clip) & 0x80000000) >> (32-RRCLIP_BOTTOMBIT))|
((AS_INT32(z_clip) & 0x80000000) >> (32-RRCLIP_FRONTBIT)) |
((AS_INT32(xx) & 0x80000000) >> (32-RRCLIP_RIGHTBIT)) |
((AS_INT32(yy) & 0x80000000) >> (32-RRCLIP_TOPBIT)) |
((AS_INT32(zz) & 0x80000000) >> (32-RRCLIP_BACKBIT));
RRCLIPCODE clipBit = RRCLIP_USERCLIPPLANE0;
for( DWORD j=0; j<RRMAX_USER_CLIPPLANES; j++)
{
if( m_xfmUserClipPlanes[j].bActive )
{
RRVECTOR4& plane = m_xfmUserClipPlanes[j].plane;
FLOAT fComp = 0.0f;
if (bPointSize)
{
// if clipping point sprites, take the sprite size into account
// and set the user clip bit if the sprite might be clipped
FLOAT x_clip_size = fPointSize*0.5f*w_clip/m_ViewData.scaleX;
FLOAT y_clip_size = fPointSize*0.5f*w_clip/m_ViewData.scaleY;
fComp = (FLOAT)sqrt(x_clip_size*x_clip_size + y_clip_size*y_clip_size);
}
if( (x_clip*plane.x +
y_clip*plane.y +
z_clip*plane.z +
w_clip*plane.w) < fComp )
{
clip |= clipBit;
}
}
clipBit <<= 1;
}
if (clip == 0)
{
*pclipIntersection = 0;
return clip;
}
else
{
if (m_dwTLState & RRPV_GUARDBAND)
{
// We do guardband check in the projection space, so
// we transform X and Y of the vertex there
D3DVALUE xnew = x_clip * m_ViewData.gb11 +
w_clip * m_ViewData.gb41;
D3DVALUE ynew = y_clip * m_ViewData.gb22 +
w_clip * m_ViewData.gb42;
D3DVALUE xx = w_clip - xnew;
D3DVALUE yy = w_clip - ynew;
clip |= ((AS_INT32(xnew) & 0x80000000) >> (32-RRCLIPGB_LEFTBIT)) |
((AS_INT32(ynew) & 0x80000000) >> (32-RRCLIPGB_BOTTOMBIT)) |
((AS_INT32(xx) & 0x80000000) >> (32-RRCLIPGB_RIGHTBIT)) |
((AS_INT32(yy) & 0x80000000) >> (32-RRCLIPGB_TOPBIT));
}
if (bPointSize)
{
// point sprite could still be visible
*pclipIntersection &= (clip & ~(RRCLIP_LEFT | RRCLIP_RIGHT | RRCLIP_TOP | RRCLIP_BOTTOM |
RRCLIP_USERCLIPPLANE0 | RRCLIP_USERCLIPPLANE1 | RRCLIP_USERCLIPPLANE2 |
RRCLIP_USERCLIPPLANE3 | RRCLIP_USERCLIPPLANE4 | RRCLIP_USERCLIPPLANE5));
}
else
{
*pclipIntersection &= clip;
}
*pclipUnion |= clip;
return clip;
}
}
//---------------------------------------------------------------------
// RRProcessVertices::ProcessVertices
//---------------------------------------------------------------------
RRCLIPCODE
RRProcessVertices::ProcessVertices()
{
D3DVERTEX *pin = (D3DVERTEX*)m_position.lpvData;
DWORD in_size = m_position.dwStride;
DWORD inFVF = m_dwFVFIn;
D3DTLVERTEX *pout = (D3DTLVERTEX*)m_pvOut;
DWORD out_size = m_dwOutputVtxSize;
UINT64 outFVF = m_qwFVFOut;
RRCLIPCODE *pclip = m_pClipBuf;
DWORD flags = m_dwTLState;
RRCLIPCODE clipIntersection = ~0;
RRCLIPCODE clipUnion = 0;
DWORD count = m_dwNumVertices;
D3DLIGHTINGELEMENT le;
BOOL bVertexInEyeSpace = FALSE;
//
// Number of vertices to blend. i.e number of blend-matrices to
// use is numVertexBlends+1.
//
int numVertexBlends = m_numVertexBlends;
m_lighting.outDiffuse = RR_DEFAULT_DIFFUSE;
m_lighting.outSpecular = RR_DEFAULT_SPECULAR;
//
// The main transform loop
//
for (DWORD i = count; i; i--)
{
const D3DVECTOR *pNormal = (D3DVECTOR *)((LPBYTE)pin +
m_dwNormalOffset);
float x_clip=0.0f, y_clip=0.0f, z_clip=0.0f, w_clip=0.0f;
float inv_w_clip=0.0f;
float *pBlendFactors = (float *)((LPBYTE)pin + sizeof( D3DVALUE )*3);
float cumulBlend = 0; // Blend accumulated so far
ZeroMemory( &le, sizeof(D3DLIGHTINGELEMENT) );
//
// Transform vertex to the clipping space, and position and normal
// into eye space, if needed.
//
for( int j=0; j<=numVertexBlends; j++)
{
float blend;
if( numVertexBlends == 0 )
{
blend = 1.0f;
}
else if( j == numVertexBlends )
{
blend = 1.0f - cumulBlend;
}
else
{
blend = pBlendFactors[j];
cumulBlend += pBlendFactors[j];
}
if (m_dwTLState & (RRPV_DOCOMPUTEPOINTSIZE|RRPV_DOPASSEYEXYZ|RRPV_DOLIGHTING))
{
le.dvPosition.x += (pin->x*m_xfmToEye[j]._11 +
pin->y*m_xfmToEye[j]._21 +
pin->z*m_xfmToEye[j]._31 +
m_xfmToEye[j]._41) * blend;
le.dvPosition.y += (pin->x*m_xfmToEye[j]._12 +
pin->y*m_xfmToEye[j]._22 +
pin->z*m_xfmToEye[j]._32 +
m_xfmToEye[j]._42) * blend;
le.dvPosition.z += (pin->x*m_xfmToEye[j]._13 +
pin->y*m_xfmToEye[j]._23 +
pin->z*m_xfmToEye[j]._33 +
m_xfmToEye[j]._43) * blend;
}
if (m_dwTLState & (RRPV_DOPASSEYENORMAL|RRPV_DOLIGHTING))
{
// Transform vertex normal to the eye space
// We use inverse transposed matrix
le.dvNormal.x += (pNormal->x*m_xfmToEyeInv[j]._11 +
pNormal->y*m_xfmToEyeInv[j]._12 +
pNormal->z*m_xfmToEyeInv[j]._13) * blend;
le.dvNormal.y += (pNormal->x*m_xfmToEyeInv[j]._21 +
pNormal->y*m_xfmToEyeInv[j]._22 +
pNormal->z*m_xfmToEyeInv[j]._23) * blend;
le.dvNormal.z += (pNormal->x*m_xfmToEyeInv[j]._31 +
pNormal->y*m_xfmToEyeInv[j]._32 +
pNormal->z*m_xfmToEyeInv[j]._33) * blend;
}
// Apply WORLDj
x_clip += (pin->x*m_xfmCurrent[j]._11 +
pin->y*m_xfmCurrent[j]._21 +
pin->z*m_xfmCurrent[j]._31 +
m_xfmCurrent[j]._41) * blend;
y_clip += (pin->x*m_xfmCurrent[j]._12 +
pin->y*m_xfmCurrent[j]._22 +
pin->z*m_xfmCurrent[j]._32 +
m_xfmCurrent[j]._42) * blend;
z_clip += (pin->x*m_xfmCurrent[j]._13 +
pin->y*m_xfmCurrent[j]._23 +
pin->z*m_xfmCurrent[j]._33 +
m_xfmCurrent[j]._43) * blend;
w_clip += (pin->x*m_xfmCurrent[j]._14 +
pin->y*m_xfmCurrent[j]._24 +
pin->z*m_xfmCurrent[j]._34 +
m_xfmCurrent[j]._44) * blend;
}
if ((flags & RRPV_NORMALIZENORMALS) && (m_dwTLState & (RRPV_DOPASSEYENORMAL|RRPV_DOLIGHTING)))
Normalize(le.dvNormal);
RRFVFExtractor VtxOut( pout, outFVF, FALSE );
FLOAT fPointSize = 0.0f;
#ifdef __POINTSPRITES
if (m_dwTLState & RRPV_DOCOMPUTEPOINTSIZE)
{
FLOAT fDist = (FLOAT)sqrt(le.dvPosition.x*le.dvPosition.x + le.dvPosition.y*le.dvPosition.y +
le.dvPosition.z*le.dvPosition.z);
if (inFVF & D3DFVF_S)
{
RRFVFExtractor VtxIn( pin, inFVF, FALSE );
fPointSize = VtxIn.GetS();
}
else
{
// from D3DRENDERSTATE_POINTSIZE
fPointSize = m_fPointSize;
}
fPointSize = fPointSize*(FLOAT)sqrt(1.0f/
(m_fPointAttA + m_fPointAttB*fDist + m_fPointAttC*fDist*fDist));
fPointSize = max(m_fPointSizeMin, fPointSize);
fPointSize = min(RRMAX_POINT_SIZE, fPointSize);
FLOAT *pfSOut = VtxOut.GetPtrS();
*pfSOut = fPointSize;
}
#endif
if (m_dwTLState & RRPV_DOPASSEYENORMAL)
{
FLOAT *pfEye = VtxOut.GetPtrEyeNormal();
pfEye[0] = le.dvNormal.x;
pfEye[1] = le.dvNormal.y;
pfEye[2] = le.dvNormal.z;
}
if (m_dwTLState & RRPV_DOPASSEYEXYZ)
{
FLOAT *pfEye = VtxOut.GetPtrEyeXYZ();
pfEye[0] = le.dvPosition.x;
pfEye[1] = le.dvPosition.y;
pfEye[2] = le.dvPosition.z;
}
//
// Compute clip codes if needed
//
if (m_dwTLState & RRPV_DOCLIPPING)
{
RRCLIPCODE clip = ComputeClipCodes(&clipIntersection, &clipUnion,
x_clip, y_clip, z_clip, w_clip, fPointSize);
if (clip == 0)
{
*pclip++ = 0;
inv_w_clip = D3DVAL(1)/w_clip;
}
else
{
if (m_dwTLState & RRPV_GUARDBAND)
{
if ((clip & ~RRCLIP_INGUARDBAND) == 0)
{
// If vertex is inside the guardband we have to compute
// screen coordinates
inv_w_clip = D3DVAL(1)/w_clip;
*pclip++ = (RRCLIPCODE)clip;
goto l_DoScreenCoord;
}
}
*pclip++ = (RRCLIPCODE)clip;
// If vertex is outside the frustum we can not compute screen
// coordinates, hence store the clip coordinates
pout->sx = x_clip;
pout->sy = y_clip;
pout->sz = z_clip;
pout->rhw = w_clip;
goto l_DoLighting;
}
}
else
{
// We have to check this only for DONOTCLIP case, because otherwise
// the vertex with "we = 0" will be clipped and screen coordinates
// will not be computed
// "clip" is not zero, if "we" is zero.
if (!FLOAT_EQZ(w_clip))
inv_w_clip = D3DVAL(1)/w_clip;
else
inv_w_clip = __HUGE_PWR2;
}
l_DoScreenCoord:
pout->sx = x_clip * inv_w_clip * m_ViewData.scaleX +
m_ViewData.offsetX;
pout->sy = y_clip * inv_w_clip * m_ViewData.scaleY +
m_ViewData.offsetY;
pout->sz = z_clip * inv_w_clip * m_ViewData.scaleZ +
m_ViewData.offsetZ;
pout->rhw = inv_w_clip;
l_DoLighting:
DWORD *pOut = (DWORD*)((char*)pout + 4*sizeof(D3DVALUE));
if (flags & RRPV_DOLIGHTING)
{
bVertexInEyeSpace = TRUE;
//
// If Diffuse color is needed, extract it for color vertex.
//
if (flags & RRPV_VERTEXDIFFUSENEEDED)
{
const DWORD color = *(DWORD*)((char*)pin + m_dwDiffuseOffset);
MakeRRCOLOR(&m_lighting.vertexDiffuse, color);
m_lighting.vertexDiffAlpha = color & 0xff000000;
}
//
// If Specular color is needed and provided
// , extract it for color vertex.
//
if (flags & RRPV_VERTEXSPECULARNEEDED)
{
const DWORD color = *(DWORD*)((char*)pin + m_dwSpecularOffset);
MakeRRCOLOR(&m_lighting.vertexSpecular, color);
m_lighting.vertexSpecAlpha = color & 0xff000000;
}
//
// Light the vertex
//
LightVertex( &le );
}
else if (inFVF & (D3DFVF_DIFFUSE | D3DFVF_SPECULAR))
{
if (inFVF & D3DFVF_DIFFUSE)
m_lighting.outDiffuse = *(DWORD*)((char*)pin + m_dwDiffuseOffset);
if (inFVF & D3DFVF_SPECULAR)
m_lighting.outSpecular = *(DWORD*)((char*)pin + m_dwSpecularOffset);
}
//
// Compute Vertex Fog if needed
//
if (flags & RRPV_DOFOG)
{
FogVertex( *(D3DVECTOR*)(pin), &le, numVertexBlends,
pBlendFactors, bVertexInEyeSpace );
}
if (outFVF & D3DFVF_DIFFUSE)
*pOut++ = m_lighting.outDiffuse;
if (outFVF & D3DFVF_SPECULAR)
*pOut++ = m_lighting.outSpecular;;
{
memcpy(pOut, (char*)pin + m_dwTexOffset, m_dwTextureCoordSizeTotal);
}
pin = (D3DVERTEX*) ((char*) pin + in_size);
pout = (D3DTLVERTEX*) ((char*) pout + out_size);
}
if (flags & RRPV_DOCLIPPING)
{
m_clipIntersection = clipIntersection;
m_clipUnion = clipUnion;
}
else
{
m_clipIntersection = 0;
m_clipUnion = 0;
}
// Returns whether all the vertices were off screen
return m_clipIntersection;
}
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////