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.
 
 
 
 
 
 

1521 lines
51 KiB

#include "pch.cpp"
#pragma hdrstop
#define GET_NEW_CLIP_VERTEX \
&m_clipping.clip_vertices[m_clipping.clip_vertices_used++];
//---------------------------------------------------------------------
inline void
InterpolateColor(RRCLIPVTX *out,
RRCLIPVTX *p1,
RRCLIPVTX *p2,
D3DVALUE num_denom )
{
int r1, g1, b1, a1;
int r2, g2, b2, a2;
r1 = RGBA_GETRED(p1->color);
g1 = RGBA_GETGREEN(p1->color);
b1 = RGBA_GETBLUE(p1->color);
a1 = RGBA_GETALPHA(p1->color);
r2 = RGBA_GETRED(p2->color);
g2 = RGBA_GETGREEN(p2->color);
b2 = RGBA_GETBLUE(p2->color);
a2 = RGBA_GETALPHA(p2->color);
out->color = RGBA_MAKE((WORD)(r1 + (r2 - r1) * num_denom),
(WORD)(g1 + (g2 - g1) * num_denom),
(WORD)(b1 + (b2 - b1) * num_denom),
(WORD)(a1 + (a2 - a1) * num_denom));
}
//---------------------------------------------------------------------
inline void
InterpolateSpecular(RRCLIPVTX *out,
RRCLIPVTX *p1,
RRCLIPVTX *p2,
D3DVALUE num_denom )
{
int r1, g1, b1, a1;
int r2, g2, b2, a2;
r1 = RGBA_GETRED(p1->specular);
g1 = RGBA_GETGREEN(p1->specular);
b1 = RGBA_GETBLUE(p1->specular);
a1 = RGBA_GETALPHA(p1->specular);
r2 = RGBA_GETRED(p2->specular);
g2 = RGBA_GETGREEN(p2->specular);
b2 = RGBA_GETBLUE(p2->specular);
a2 = RGBA_GETALPHA(p2->specular);
out->specular = RGBA_MAKE((WORD)(r1 + (r2 - r1) * num_denom),
(WORD)(g1 + (g2 - g1) * num_denom),
(WORD)(b1 + (b2 - b1) * num_denom),
(WORD)(a1 + (a2 - a1) * num_denom));
}
//---------------------------------------------------------------------
// Inline texture coordinate difference.
__inline FLOAT
TextureDiff(FLOAT fTb, FLOAT fTa, INT iMode)
{
FLOAT fDiff1 = fTb - fTa;
if (iMode == 0)
{
// Wrap not set, return plain difference.
return fDiff1;
}
else
{
FLOAT fDiff2;
// Wrap set, compute shortest distance of plain difference
// and wrap difference.
fDiff2 = fDiff1;
if (FLOAT_LTZ(fDiff1))
{
fDiff2 += g_fOne;
}
else if (FLOAT_GTZ(fDiff1))
{
fDiff2 -= g_fOne;
}
if (ABSF(fDiff1) < ABSF(fDiff2))
{
return fDiff1;
}
else
{
return fDiff2;
}
}
}
//---------------------------------------------------------------------
inline D3DVALUE
InterpolateTexture(D3DVALUE t1,
D3DVALUE t2,
D3DVALUE num_denom,
DWORD bWrap)
{
if (!bWrap)
{
return ((t2 - t1) * num_denom + t1);
}
else
{
D3DVALUE t = (TextureDiff(t2, t1, 1) * num_denom + t1);
if (t > 1.0f) t -= 1.0f;
return t;
}
}
//
// Clipping a triangle by a plane
//
// Returns number of vertices in the clipped triangle
//
int
RRProcessVertices::ClipByPlane( RRCLIPVTX **inv,
RRCLIPVTX **outv,
RRVECTOR4 *plane,
DWORD dwClipFlag,
int count )
{
int i;
int out_count = 0;
RRCLIPVTX *curr, *prev;
D3DVALUE curr_inside;
D3DVALUE prev_inside;
prev = inv[count-1];
curr = *inv++;
prev_inside = prev->hx*plane->x + prev->hy*plane->y +
prev->hz*plane->z + prev->hw*plane->w;
for (i = count; i; i--)
{
curr_inside = curr->hx*plane->x + curr->hy*plane->y +
curr->hz*plane->z + curr->hw*plane->w;
// We interpolate always from the inside vertex to the outside vertex
// to reduce precision problems
if (FLOAT_LTZ(prev_inside))
{ // first point is outside
if (FLOAT_GEZ(curr_inside))
{ // second point is inside
// Find intersection and insert in into the output buffer
outv[out_count] = GET_NEW_CLIP_VERTEX;
Interpolate( outv[out_count],
curr, prev,
(prev->clip & CLIPPED_ENABLE) | dwClipFlag,
curr_inside, curr_inside - prev_inside);
out_count++;
}
} else
{ // first point is inside - put it to the output buffer first
outv[out_count++] = prev;
if (FLOAT_LTZ(curr_inside))
{ // second point is outside
// Find intersection and put it to the output buffer
outv[out_count] = GET_NEW_CLIP_VERTEX;
Interpolate( outv[out_count],
prev, curr,
dwClipFlag,
prev_inside, prev_inside - curr_inside);
out_count++;
}
}
prev = curr;
curr = *inv++;
prev_inside = curr_inside;
}
return out_count;
}
//-------------------------------------------------------------------------
// Clips a line by a plane
//
// Returns 1 if the line is outside the frustum, 0 otherwise
//
int
RRProcessVertices::ClipLineByPlane(RRCLIPTRIANGLE *line,
RRVECTOR4 *plane,
DWORD dwClipBit)
{
D3DVALUE in1, in2;
RRCLIPVTX outv;
in1 = line->v[0]->hx * plane->x +
line->v[0]->hy * plane->y +
line->v[0]->hz * plane->z +
line->v[0]->hw * plane->w;
in2 = line->v[1]->hx * plane->x +
line->v[1]->hy * plane->y +
line->v[1]->hz * plane->z +
line->v[1]->hw * plane->w;
if (in1 < 0)
{
if (in2 < 0)
return 1;
Interpolate( &outv, line->v[0], line->v[1],
dwClipBit, in1, in1 - in2);
*line->v[0] = outv;
}
else
{
if (in2 < 0)
{
Interpolate( &outv, line->v[0], line->v[1],
dwClipBit, in1, in1 - in2);
*line->v[1] = outv;
}
}
return 0;
}
/*------------------------------------------------------------------------
* Calculate the screen coords for any new vertices
* introduced into the polygon.
*/
void
ComputeScreenCoordinates(const RRVIEWPORTDATA& VData,
RRCLIPVTX **inv, int count)
{
int i;
for (i = 0; i < count; i++)
{
RRCLIPVTX *p;
p = inv[i];
/*
* Catch any vertices that need screen co-ordinates generated.
* There are two possibilities
* 1) Vertices generated during interpolation
* 2) Vertices marked for clipping by the transform but
* not clipped here due to the finite precision
* of the floating point unit.
*/
if (p->clip & ~CLIPPED_ENABLE)
{
D3DVALUE w;
w = D3DVAL(1.0)/p->hw;
switch ((int)p->clip & (CLIPPED_LEFT|CLIPPED_RIGHT))
{
case CLIPPED_LEFT: p->sx = VData.minXgb; break;
case CLIPPED_RIGHT: p->sx = VData.maxXgb; break;
default:
p->sx = p->hx * VData.scaleX * w + VData.offsetX;
if (p->sx < VData.minXgb)
p->sx = VData.minXgb;
if (p->sx > VData.maxXgb)
p->sx = VData.maxXgb;
}
switch ((int)p->clip & (CLIPPED_TOP|CLIPPED_BOTTOM))
{
case CLIPPED_BOTTOM: p->sy = VData.maxYgb; break;
case CLIPPED_TOP: p->sy = VData.minYgb; break;
default:
p->sy = p->hy * VData.scaleY * w + VData.offsetY;
if (p->sy < VData.minYgb)
p->sy = VData.minYgb;
if (p->sy > VData.maxYgb)
p->sy = VData.maxYgb;
}
p->sz = p->hz * VData.scaleZ * w + VData.offsetZ;
p->rhw = w;
}
}
}
//---------------------------------------------------------------------
void
RRProcessVertices::Interpolate(RRCLIPVTX *out,
RRCLIPVTX *p1,
RRCLIPVTX *p2,
int code,
D3DVALUE num,
D3DVALUE denom)
{
DWORD dwInterpolate = m_clipping.dwInterpolate;
D3DVALUE num_denom = num / denom;
out->clip = (((int)p1->clip & (int)p2->clip) & ~CLIPPED_ENABLE) | code;
out->hx = p1->hx + (p2->hx - p1->hx) * num_denom;
out->hy = p1->hy + (p2->hy - p1->hy) * num_denom;
out->hz = p1->hz + (p2->hz - p1->hz) * num_denom;
out->hw = p1->hw + (p2->hw - p1->hw) * num_denom;
out->color = m_clipping.clip_color;
out->specular = m_clipping.clip_specular;
/*
* Interpolate any other color model or quality dependent values.
*/
if (dwInterpolate & RRCLIP_INTERPOLATE_COLOR)
{
InterpolateColor(out, p1, p2, num_denom);
}
if (dwInterpolate & RRCLIP_INTERPOLATE_SPECULAR)
{
InterpolateSpecular(out, p1, p2, num_denom);
}
if (dwInterpolate & RRCLIP_INTERPOLATE_TEXTURE)
{
// Assume that D3DRENDERSTATE_WRAPi are sequential
D3DVALUE *pTexture1 = p1->tex;
D3DVALUE *pTexture2 = p2->tex;
D3DVALUE *pTexture = out->tex;
for (DWORD i = 0; i < m_dwNumTexCoords; i++)
{
DWORD wrapState = ((ReferenceRasterizer *)this)->GetRenderState()[D3DRENDERSTATE_WRAP0 + i];
DWORD n = (DWORD)(m_dwTexCoordSize[i] >> 2);
DWORD dwWrapBit = 1;
for (DWORD j=0; j < n; j++)
{
*pTexture = InterpolateTexture(*pTexture1, *pTexture2,
num_denom,
wrapState & dwWrapBit);
dwWrapBit <<= 1;
pTexture ++;
pTexture1++;
pTexture2++;
}
}
}
if (dwInterpolate & RRCLIP_INTERPOLATE_S)
{
out->s = p1->s + (p2->s - p1->s) * num_denom;
}
if (dwInterpolate & RRCLIP_INTERPOLATE_EYENORMAL)
{
out->eyenx = p1->eyenx + (p2->eyenx - p1->eyenx) * num_denom;
out->eyeny = p1->eyeny + (p2->eyeny - p1->eyeny) * num_denom;
out->eyenz = p1->eyenz + (p2->eyenz - p1->eyenz) * num_denom;
}
if (dwInterpolate & RRCLIP_INTERPOLATE_EYEXYZ)
{
out->eyex = p1->eyex + (p2->eyex - p1->eyex) * num_denom;
out->eyey = p1->eyey + (p2->eyey - p1->eyey) * num_denom;
out->eyez = p1->eyez + (p2->eyez - p1->eyez) * num_denom;
}
}
//------------------------------------------------------------------------------
// Functions for clipping by frustum window
//
#define __CLIP_NAME ClipLeft
#define __CLIP_LINE_NAME ClipLineLeft
#define __CLIP_FLAG CLIPPED_LEFT
#define __CLIP_COORD hx
#include "clip.h"
#define __CLIP_NAME ClipRight
#define __CLIP_LINE_NAME ClipLineRight
#define __CLIP_W
#define __CLIP_FLAG CLIPPED_RIGHT
#define __CLIP_COORD hx
#include "clip.h"
#define __CLIP_NAME ClipBottom
#define __CLIP_LINE_NAME ClipLineBottom
#define __CLIP_FLAG CLIPPED_BOTTOM
#define __CLIP_COORD hy
#include "clip.h"
#define __CLIP_NAME ClipTop
#define __CLIP_LINE_NAME ClipLineTop
#define __CLIP_W
#define __CLIP_FLAG CLIPPED_TOP
#define __CLIP_COORD hy
#include "clip.h"
#define __CLIP_NAME ClipBack
#define __CLIP_LINE_NAME ClipLineBack
#define __CLIP_W
#define __CLIP_FLAG CLIPPED_BACK
#define __CLIP_COORD hz
#include "clip.h"
#define __CLIP_NAME ClipFront
#define __CLIP_LINE_NAME ClipLineFront
#define __CLIP_FLAG CLIPPED_FRONT
#define __CLIP_COORD hz
#include "clip.h"
//------------------------------------------------------------------------------
// Functions for guard band clipping
//
#define __CLIP_GUARDBAND
#define __CLIP_NAME ClipLeftGB
#define __CLIP_LINE_NAME ClipLineLeftGB
#define __CLIP_FLAG CLIPPED_LEFT
#define __CLIP_COORD hx
#define __CLIP_SIGN -
#define __CLIP_GBCOEF Kgbx1
#include "clip.h"
#define __CLIP_NAME ClipRightGB
#define __CLIP_LINE_NAME ClipLineRightGB
#define __CLIP_FLAG CLIPPED_RIGHT
#define __CLIP_COORD hx
#define __CLIP_GBCOEF Kgbx2
#define __CLIP_SIGN +
#include "clip.h"
#define __CLIP_NAME ClipBottomGB
#define __CLIP_LINE_NAME ClipLineBottomGB
#define __CLIP_FLAG CLIPPED_BOTTOM
#define __CLIP_COORD hy
#define __CLIP_SIGN -
#define __CLIP_GBCOEF Kgby1
#include "clip.h"
#define __CLIP_NAME ClipTopGB
#define __CLIP_LINE_NAME ClipLineTopGB
#define __CLIP_FLAG CLIPPED_TOP
#define __CLIP_COORD hy
#define __CLIP_GBCOEF Kgby2
#define __CLIP_SIGN +
#include "clip.h"
#undef __CLIP_GUARDBAND
//---------------------------------------------------------------------
inline DWORD ComputeClipCodeUserPlanes( RRUSERCLIPPLANE *UserPlanes,
RRCLIPVTX *p)
{
DWORD clip = 0;
DWORD dwClipBit = RRCLIP_USERCLIPPLANE0;
for( DWORD j=0; j<RRMAX_USER_CLIPPLANES; j++)
{
if( UserPlanes[j].bActive )
{
RRVECTOR4& plane = UserPlanes[j].plane;
if( (p->hx*plane.x +
p->hy*plane.y +
p->hz*plane.z +
p->hw*plane.w) < 0 )
{
clip |= dwClipBit;
}
}
dwClipBit <<= 1;
}
return clip;
}
//---------------------------------------------------------------------
inline DWORD ComputeClipCodeGB(const RRVIEWPORTDATA& VData,
RRUSERCLIPPLANE *UserPlanes, RRCLIPVTX *p)
{
DWORD clip = 0;
if (p->hx < p->hw * VData.Kgbx1)
clip |= RRCLIPGB_LEFT;
if (p->hx > p->hw * VData.Kgbx2)
clip |= RRCLIPGB_RIGHT;
if (p->hy < p->hw * VData.Kgby1)
clip |= RRCLIPGB_BOTTOM;
if (p->hy > p->hw * VData.Kgby2)
clip |= RRCLIPGB_TOP;
if (p->hz > p->hw)
clip |= RRCLIP_BACK;
clip |= ComputeClipCodeUserPlanes(UserPlanes, p);
p->clip = (p->clip & (CLIPPED_ENABLE | CLIPPED_FRONT)) | clip;
return clip;
}
//---------------------------------------------------------------------
inline DWORD ComputeClipCode(RRUSERCLIPPLANE *UserPlanes, RRCLIPVTX *p)
{
DWORD clip = 0;
if (FLOAT_LTZ(p->hx))
clip |= RRCLIP_LEFT;
if (p->hx > p->hw)
clip |= RRCLIP_RIGHT;
if (FLOAT_LTZ(p->hy))
clip |= RRCLIP_BOTTOM;
if (p->hy > p->hw)
clip |= RRCLIP_TOP;
if (p->hz > p->hw)
clip |= RRCLIP_BACK;
clip |= ComputeClipCodeUserPlanes(UserPlanes, p);
p->clip = (p->clip & (CLIPPED_ENABLE | CLIPPED_FRONT)) | clip;
return clip;
}
//---------------------------------------------------------------------
// RRProcessVertices::UpdateClippingData
// Updates clipping data used by ProcessVertices
//---------------------------------------------------------------------
HRESULT
RRProcessVertices::UpdateClippingData( DWORD dwClipPlanesEnable )
{
HRESULT hr = D3D_OK;
// Update the user defined clip plane data
for( DWORD i=0; i<RRMAX_USER_CLIPPLANES; i++ )
{
// Figure out if it is active
m_xfmUserClipPlanes[i].bActive = (BOOL)(dwClipPlanesEnable & 0x1);
dwClipPlanesEnable >>= 1;
// If it is active, transform it into eye-space using the
// view transform. The clip planes are defined in the
// world space.
if( m_xfmUserClipPlanes[i].bActive )
{
XformPlaneBy4x4Transposed( &m_userClipPlanes[i],
&m_TransformData.m_VPSInv,
&m_xfmUserClipPlanes[i].plane );
}
}
m_dwDirtyFlags &= ~(RRPV_DIRTY_CLIPPLANES);
return hr;
}
//----------------------------------------------------------------------------
//
// DrawOneClippedPrimitive
//
// Draw one clipped primitive.
//
//----------------------------------------------------------------------------
HRESULT
RRProcessVertices::DrawOneClippedPrimitive()
{
INT i;
PUINT8 pV0, pV1, pV2;
HRESULT hr;
PUINT8 pVtx = (PUINT8) m_pvOut;
RRCLIPCODE *pClip = m_pClipBuf;
RRCLIPCODE c0, c1, c2;
switch (m_primType)
{
case D3DPT_POINTLIST:
for (i = (INT)m_dwNumVertices; i > 0; i--)
{
c0 = *pClip++;
((ReferenceRasterizer *)this)->DrawClippedPoint(pVtx, c0);
pVtx += m_dwOutputVtxSize;
}
break;
case D3DPT_LINELIST:
for (i = (INT)m_dwNumVertices / 2; i > 0; i--)
{
pV0 = pVtx;
pVtx += m_dwOutputVtxSize;
c0 = *pClip++;
pV1 = pVtx;
pVtx += m_dwOutputVtxSize;
c1 = *pClip++;
((ReferenceRasterizer *)this)->DrawClippedLine(pV0, c0,
pV1, c1);
}
break;
case D3DPT_LINESTRIP:
{
pV1 = pVtx;
c1 = *pClip;
// Disable last-pixel setting for shared verties and store prestate.
((ReferenceRasterizer *)this)->StoreLastPixelState(TRUE);
// Initial pV0.
for (i = (INT)m_dwNumVertices - 1; i > 1; i--)
{
pV0 = pV1;
c0 = c1;
pVtx += m_dwOutputVtxSize;
pV1 = pVtx;
c1 = *(++pClip);
((ReferenceRasterizer *)this)->DrawClippedLine(pV0, c0,
pV1, c1);
}
// Restore last-pixel setting.
((ReferenceRasterizer *)this)->StoreLastPixelState(FALSE);
// Draw last line with last-pixel setting from state.
if (i == 1)
{
pV0 = pVtx + m_dwOutputVtxSize;
c0 = *(++pClip);
((ReferenceRasterizer *)this)->DrawClippedLine(pV1, c1,
pV0, c0);
}
}
break;
case D3DPT_TRIANGLELIST:
for (i = (INT)m_dwNumVertices; i > 0; i -= 3)
{
pV0 = pVtx;
pVtx += m_dwOutputVtxSize;
c0 = *pClip++;
pV1 = pVtx;
pVtx += m_dwOutputVtxSize;
c1 = *pClip++;
pV2 = pVtx;
pVtx += m_dwOutputVtxSize;
c2 = *pClip++;
((ReferenceRasterizer *)this)->DrawClippedTriangle(pV0, c0,
pV1, c1,
pV2, c2);
}
break;
case D3DPT_TRIANGLESTRIP:
{
// Get initial vertex values.
pV1 = pVtx;
pVtx += m_dwOutputVtxSize;
c1 = *pClip++;
pV2 = pVtx;
pVtx += m_dwOutputVtxSize;
c2 = *pClip++;
for (i = (INT)m_dwNumVertices - 2; i > 1; i -= 2)
{
pV0 = pV1; c0 = c1;
pV1 = pV2; c1 = c2;
pV2 = pVtx;
pVtx += m_dwOutputVtxSize;
c2 = *pClip++;
((ReferenceRasterizer *)this)->DrawClippedTriangle(pV0, c0,
pV1, c1,
pV2, c2);
pV0 = pV1; c0 = c1;
pV1 = pV2; c1 = c2;
pV2 = pVtx;
pVtx += m_dwOutputVtxSize;
c2 = *pClip++;
((ReferenceRasterizer *)this)->DrawClippedTriangle(pV0, c0,
pV2, c2,
pV1, c1);
}
if (i > 0)
{
pV0 = pV1; c0 = c1;
pV1 = pV2; c1 = c2;
pV2 = pVtx; c2 = *pClip;
((ReferenceRasterizer *)this)->DrawClippedTriangle(pV0, c0,
pV1, c1,
pV2, c2);
}
}
break;
case D3DPT_TRIANGLEFAN:
{
RRCLIPCODE c0, c1, c2;
pV2 = pVtx;
pVtx += m_dwOutputVtxSize;
c2 = *pClip++;
// Preload initial pV0.
pV1 = pVtx;
pVtx += m_dwOutputVtxSize;
c1 = *pClip++;
for (i = (INT)m_dwNumVertices - 2; i > 0; i--)
{
pV0 = pV1; c0 = c1;
pV1 = pVtx;
pVtx += m_dwOutputVtxSize;
c1 = *pClip++;
((ReferenceRasterizer *)this)->DrawClippedTriangle(pV0, c0,
pV1, c1,
pV2, c2);
}
}
break;
default:
DPFM(0, DRV, ("Refrast Error: Unknown or unsupported primitive type "
"requested of DrawOnePrimitive"));
return DDERR_INVALIDPARAMS;
}
return D3D_OK;
}
//----------------------------------------------------------------------------
//
// DrawOneClippedIndexedPrimitive
//
// Draw one list of clipped indexed primitives.
//
//----------------------------------------------------------------------------
HRESULT
RRProcessVertices::DrawOneClippedIndexedPrimitive()
{
INT i;
PUINT8 pVtx = (PUINT8) m_pvOut;
LPWORD puIndices = m_pIndices;
PUINT8 pV0, pV1, pV2;
RRCLIPCODE *pClip = m_pClipBuf;
RRCLIPCODE c0, c1, c2;
HRESULT hr;
switch(m_primType)
{
case D3DPT_POINTLIST:
for (i = (INT)m_dwNumIndices; i > 0; i--)
{
c0 = pClip[*puIndices];
pV0 = pVtx + m_dwOutputVtxSize * (*puIndices++);
((ReferenceRasterizer *)this)->DrawClippedPoint(pV0, c0);
}
break;
case D3DPT_LINELIST:
for (i = (INT)m_dwNumIndices / 2; i > 0; i--)
{
c0 = pClip[*puIndices];
pV0 = pVtx + m_dwOutputVtxSize * (*puIndices++);
c1 = pClip[*puIndices];
pV1 = pVtx + m_dwOutputVtxSize * (*puIndices++);
((ReferenceRasterizer *)this)->DrawClippedLine(pV0, c0,
pV1, c1);
}
break;
case D3DPT_LINESTRIP:
{
// Disable last-pixel setting for shared verties and store prestate.
((ReferenceRasterizer *)this)->StoreLastPixelState(TRUE);
// Initial pV1.
c1 = pClip[*puIndices];
pV1 = pVtx + m_dwOutputVtxSize * (*puIndices++);
for (i = (INT)m_dwNumIndices - 1; i > 1; i--)
{
c0 = c1;
pV0 = pV1;
c1 = pClip[*puIndices];
pV1 = pVtx + m_dwOutputVtxSize * (*puIndices++);
((ReferenceRasterizer *)this)->DrawClippedLine(pV0, c0,
pV1, c1);
}
// Restore last-pixel setting.
((ReferenceRasterizer *)this)->StoreLastPixelState(FALSE);
// Draw last line with last-pixel setting from state.
if (i == 1)
{
c0 = pClip[*puIndices];
pV0 = pVtx + m_dwOutputVtxSize * (*puIndices);
((ReferenceRasterizer *)this)->DrawClippedLine(pV1, c1,
pV0, c0);
}
}
break;
case D3DPT_TRIANGLELIST:
for (i = (INT)m_dwNumIndices; i > 0; i -= 3)
{
c0 = pClip[*puIndices];
pV0 = pVtx + m_dwOutputVtxSize * (*puIndices++);
c1 = pClip[*puIndices];
pV1 = pVtx + m_dwOutputVtxSize * (*puIndices++);
c2 = pClip[*puIndices];
pV2 = pVtx + m_dwOutputVtxSize * (*puIndices++);
((ReferenceRasterizer *)this)->DrawClippedTriangle(pV0, c0,
pV1, c1,
pV2, c2);
}
break;
case D3DPT_TRIANGLESTRIP:
{
// Get initial vertex values.
c1 = pClip[*puIndices];
pV1 = pVtx + m_dwOutputVtxSize * (*puIndices++);
c2 = pClip[*puIndices];
pV2 = pVtx + m_dwOutputVtxSize * (*puIndices++);
for (i = (INT)m_dwNumIndices - 2; i > 1; i -= 2)
{
c0 = c1; pV0 = pV1;
c1 = c2; pV1 = pV2;
c2 = pClip[*puIndices];
pV2 = pVtx + m_dwOutputVtxSize * (*puIndices++);
((ReferenceRasterizer *)this)->DrawClippedTriangle(pV0, c0,
pV1, c1,
pV2, c2);
c0 = c1; pV0 = pV1;
c1 = c2; pV1 = pV2;
c2 = pClip[*puIndices];
pV2 = pVtx + m_dwOutputVtxSize * (*puIndices++);
((ReferenceRasterizer *)this)->DrawClippedTriangle(pV0, c0,
pV2, c2,
pV1, c1);
}
if (i > 0)
{
c0 = c1; pV0 = pV1;
c1 = c2; pV1 = pV2;
c2 = pClip[*puIndices];
pV2 = pVtx + m_dwOutputVtxSize * (*puIndices++);
((ReferenceRasterizer *)this)->DrawClippedTriangle(pV0, c0,
pV1, c1,
pV2, c2);
}
}
break;
case D3DPT_TRIANGLEFAN:
{
c2 = pClip[*puIndices];
pV2 = pVtx + m_dwOutputVtxSize * (*puIndices++);
// Preload initial pV0.
c1 = pClip[*puIndices];
pV1 = pVtx + m_dwOutputVtxSize * (*puIndices++);
for (i = (INT)m_dwNumIndices - 2; i > 0; i--)
{
c0 = c1; pV0 = pV1;
c1 = pClip[*puIndices];
pV1 = pVtx + m_dwOutputVtxSize * (*puIndices++);
((ReferenceRasterizer *)this)->DrawClippedTriangle(pV0, c0,
pV1, c1,
pV2, c2);
}
}
break;
default:
DPFM(0, DRV, ("Refrast Error: Unknown or unsupported primitive type "
"requested of DrawOneClippedIndexedPrimitive"));
return DDERR_INVALIDPARAMS;
}
return D3D_OK;
}
///////////////////////////////////////////////////////////////////////////////
//
///////////////////////////////////////////////////////////////////////////////
void
ReferenceRasterizer::DrawClippedTriangle( void* pvV0, RRCLIPCODE c0,
void* pvV1, RRCLIPCODE c1,
void* pvV2, RRCLIPCODE c2,
WORD wFlags )
{
DWORD dwInter = (c0 & c1 & c2);
DWORD dwUnion = (c0 | c1 | c2);
DWORD dwMask = (m_dwTLState & RRPV_GUARDBAND) ? RRCLIPGB_ALL : RRCLIP_ALL;
// All vertices outside the frustum or guardband,
// return without drawing
if (dwInter)
{
return;
}
// If all the vertices are in, draw and return
if ((dwUnion & dwMask) == 0)
{
DrawTriangle( pvV0, pvV1, pvV2, wFlags );
return;
}
// Do Clipping
RRCLIPTRIANGLE newtri;
RRCLIPVTX cv[3];
MakeClipVertexFromFVF( cv[0], pvV0, m_ViewData,
m_dwTextureCoordSizeTotal, m_qwFVFOut, c0,
dwMask);
MakeClipVertexFromFVF( cv[1], pvV1, m_ViewData,
m_dwTextureCoordSizeTotal, m_qwFVFOut, c1,
dwMask);
MakeClipVertexFromFVF( cv[2], pvV2, m_ViewData,
m_dwTextureCoordSizeTotal, m_qwFVFOut, c2,
dwMask);
newtri.v[0] = &cv[0]; cv[0].next = &cv[1];
newtri.v[1] = &cv[1]; cv[1].next = &cv[2];
newtri.v[2] = &cv[2]; cv[2].next = NULL;
int count;
RRCLIPVTX **ver;
cv[0].clip |= CLIPPED_ENABLE;
cv[1].clip |= CLIPPED_ENABLE;
cv[2].clip |= CLIPPED_ENABLE;
if (count = ClipSingleTriangle( &newtri, &ver ))
{
int i;
// Temporary Byte Array
if (m_clipping.ClipBuf.GetSize() < m_dwOutputVtxSize*count)
{
m_clipping.ClipBuf.Grow( m_dwOutputVtxSize*count );
}
LPBYTE pTLV = (LPBYTE)m_clipping.ClipBuf.GetAddress();
LPBYTE p = pTLV;
for (i = 0; i < count; i++)
{
MakeFVFVertexFromClip( p, ver[i], m_qwFVFOut,
m_dwTextureCoordSizeTotal);
p += m_dwOutputVtxSize;
}
// If it is in wireframe mode, convert the clipper output to
// a line list.
if (!m_bPointSprite && (GetRenderState()[D3DRENDERSTATE_FILLMODE] == D3DFILL_WIREFRAME))
{
DWORD dwEdgeFlags = 0;
for (i = 0; i < count; i++)
{
if (ver[i]->clip & CLIPPED_ENABLE) dwEdgeFlags |= (1 << i);
p += m_dwOutputVtxSize;
}
DoDrawOneEdgeFlagTriangleFan( this, m_dwOutputVtxSize,
(PUINT8) pTLV, count,
dwEdgeFlags );
}
else
{
DoDrawOnePrimitive( this, m_dwOutputVtxSize, (PUINT8) pTLV,
D3DPT_TRIANGLEFAN, count);
}
}
}
void
ReferenceRasterizer::DrawClippedLine( void* pvV0, RRCLIPCODE c0,
void* pvV1, RRCLIPCODE c1,
void* pvVFlat )
{
DWORD dwInter = (c0 & c1);
DWORD dwUnion = (c0 | c1);
DWORD dwMask = (m_dwTLState & RRPV_GUARDBAND) ? RRCLIPGB_ALL : RRCLIP_ALL;
// All vertices outside the frustum or guardband,
// return without drawing
if (dwInter)
{
return;
}
// If all the vertices are in, draw and return
if ((dwUnion & dwMask) == 0)
{
DrawLine( pvV0, pvV1, pvVFlat );
return;
}
RRCLIPTRIANGLE newline;
RRCLIPVTX cv[2];
MakeClipVertexFromFVF( cv[0], pvV0, m_ViewData,
m_dwTextureCoordSizeTotal, m_qwFVFOut, c0,
dwMask);
MakeClipVertexFromFVF( cv[1], pvV1, m_ViewData,
m_dwTextureCoordSizeTotal, m_qwFVFOut, c1,
dwMask);
newline.v[0] = &cv[0];
newline.v[1] = &cv[1];
if (ClipSingleLine( &newline ))
{
// Temporary Byte Array
if (m_clipping.ClipBuf.GetSize() < m_dwOutputVtxSize*2)
{
m_clipping.ClipBuf.Grow( m_dwOutputVtxSize*3 );
}
LPBYTE pTLV = (LPBYTE)m_clipping.ClipBuf.GetAddress();
LPBYTE p = pTLV;
MakeFVFVertexFromClip( p, newline.v[0], m_qwFVFOut,
m_dwTextureCoordSizeTotal);
p += m_dwOutputVtxSize;
MakeFVFVertexFromClip( p, newline.v[1], m_qwFVFOut,
m_dwTextureCoordSizeTotal);
DrawLine( pTLV, p, pvVFlat );
}
}
void
ReferenceRasterizer::DrawClippedPoint( void* pvV0, RRCLIPCODE c0,
void* pvVFlat )
{
// if definitely out
if (c0 & (RRCLIP_FRONT | RRCLIP_BACK | (1<<RRCLIPGB_LEFTBIT) | (1<<RRCLIPGB_RIGHTBIT) |
(1<<RRCLIPGB_TOPBIT) | (1<<RRCLIPGB_BOTTOMBIT)))
return;
// otherwise, could be in
if (c0 == 0)
{
// is completely in, just draw it
DrawPoint( pvV0, pvVFlat );
}
else
{
// use per vertex S if it exists, otherwise use D3DRENDERSTATE_POINTSIZE
BOOL bAlreadyXfmd = FVF_TRANSFORMED( m_dwFVFIn );
RRFVFExtractor Vtx0( pvV0, m_qwFVFControl, m_dwRenderState[D3DRENDERSTATE_TEXTUREPERSPECTIVE] );
FLOAT fS = 1.0f;
#ifdef __POINTSPRITES
if (m_qwFVFControl & D3DFVF_S)
{
fS = Vtx0.GetS();
}
else if( m_dwDriverType > RRTYPE_DP2HAL )
{
fS = m_fRenderState[D3DRENDERSTATE_POINTSIZE];
}
#endif
if (fS <= 1.0f)
{
// too small and out
return;
}
#ifdef __POINTSPRITES
if (c0 & (RRCLIP_USERCLIPPLANE0 | RRCLIP_USERCLIPPLANE1 | RRCLIP_USERCLIPPLANE2 |
RRCLIP_USERCLIPPLANE3 | RRCLIP_USERCLIPPLANE4 | RRCLIP_USERCLIPPLANE5))
{
// large and potentially clipped, expand point sprite to quad and clip traditionally
fS *= 0.5f; // turn size into screen space offset to quad points from center
FLOAT w_clip = Vtx0.GetRHW(); // not really the reciprocal
FLOAT x_clip_size = fS*w_clip/m_ViewData.scaleX;
FLOAT y_clip_size = fS*w_clip/m_ViewData.scaleY;
UINT64 qwFVFControlSave = m_qwFVFControl;
UINT64 qwFVFOutSave = m_qwFVFOut;
DWORD dwOutputVtxSizeSave = m_dwOutputVtxSize;
DWORD dwTextureCoordSizeTotalSave = m_dwTextureCoordSizeTotal;
DWORD dwTexCoordSizeSave[D3DDP_MAXTEXCOORD];
memcpy(dwTexCoordSizeSave, m_dwTexCoordSize, sizeof(DWORD)*D3DDP_MAXTEXCOORD);
DWORD dwInterpolateSave = m_clipping.dwInterpolate;
DWORD dwNumTexCoordsSave = m_dwNumTexCoords;
INT32 iTexCount = 0;
if (m_dwRenderState[D3DRENDERSTATE_POINTSPRITEENABLE] && m_cActiveTextureStages)
{
// look through texture stages to see how many texture indices are needed
// since for POINTSPRITE mode, the input vertices don't even have to have any
// texture coordinates. Since this is an important advantage of using point
// sprites, we have to deal with it.
for ( INT32 iStage=0; iStage<m_cActiveTextureStages; iStage++ )
{
if (m_pTexture[iStage])
{
INT32 iCoordSet = m_pTexture[iStage]->m_pStageState[iStage].m_dwVal[D3DTSS_TEXCOORDINDEX];
iCoordSet &= 0xffff;
iTexCount = max(iCoordSet+1, iTexCount);
m_clipping.dwInterpolate |= RRCLIP_INTERPOLATE_TEXTURE;
}
}
}
m_qwFVFOut &= ~(D3DFVF_TEXCOUNT_MASK | 0xffff0000);
m_qwFVFOut |= (iTexCount << D3DFVF_TEXCOUNT_SHIFT) & D3DFVF_TEXCOUNT_MASK;
m_qwFVFControl = m_qwFVFOut;
m_dwNumTexCoords = FVF_TEXCOORD_NUMBER((DWORD)m_qwFVFOut);
m_dwOutputVtxSize = GetFVFVertexSize( m_qwFVFOut );
m_dwTextureCoordSizeTotal = 0;
ComputeTextureCoordSize((DWORD)m_qwFVFOut, m_dwTexCoordSize,
&m_dwTextureCoordSizeTotal);
void *pvVT0, *pvVT1, *pvVT2, *pvVT3;
{
pvVT0 = MEMALLOC( m_dwOutputVtxSize );
pvVT1 = MEMALLOC( m_dwOutputVtxSize );
pvVT2 = MEMALLOC( m_dwOutputVtxSize );
pvVT3 = MEMALLOC( m_dwOutputVtxSize );
_ASSERTa( ( NULL != pvVT0 ) && ( NULL != pvVT1 ) && ( NULL != pvVT2) && (NULL != pvVT2),
"malloc failure on ReferenceRasterizer::DrawClippedPoint", return; );
// only copy as much data as we have
DWORD dwStride = GetFVFVertexSize(qwFVFControlSave);
memcpy(pvVT0, pvV0, dwStride);
memcpy(pvVT1, pvV0, dwStride);
memcpy(pvVT2, pvV0, dwStride);
memcpy(pvVT3, pvV0, dwStride);
}
// encase FVF vertex pointer and control in class to extract fields
RRFVFExtractor VtxT0( pvVT0, m_qwFVFControl, m_dwRenderState[D3DRENDERSTATE_TEXTUREPERSPECTIVE] );
RRFVFExtractor VtxT1( pvVT1, m_qwFVFControl, m_dwRenderState[D3DRENDERSTATE_TEXTUREPERSPECTIVE] );
RRFVFExtractor VtxT2( pvVT2, m_qwFVFControl, m_dwRenderState[D3DRENDERSTATE_TEXTUREPERSPECTIVE] );
RRFVFExtractor VtxT3( pvVT3, m_qwFVFControl, m_dwRenderState[D3DRENDERSTATE_TEXTUREPERSPECTIVE] );
FLOAT *pXY = VtxT0.GetPtrXYZ();
pXY[0] += -x_clip_size;
pXY[1] += -y_clip_size;
pXY = VtxT1.GetPtrXYZ();
pXY[0] += x_clip_size;
pXY[1] += -y_clip_size;
pXY = VtxT2.GetPtrXYZ();
pXY[0] += -x_clip_size;
pXY[1] += y_clip_size;
pXY = VtxT3.GetPtrXYZ();
pXY[0] += x_clip_size;
pXY[1] += y_clip_size;
if (m_dwRenderState[D3DRENDERSTATE_POINTSPRITEENABLE] && m_cActiveTextureStages)
{
// compute functions for texture coordinates
if (m_cActiveTextureStages)
{
for ( INT32 iStage=0; iStage<m_cActiveTextureStages; iStage++ )
{
if (m_pTexture[iStage])
{
INT32 iCoordSet = m_pTexture[iStage]->m_pStageState[iStage].m_dwVal[D3DTSS_TEXCOORDINDEX];
iCoordSet &= 0xffff;
FLOAT *pUV = VtxT0.GetPtrTexCrd(0, iCoordSet);
pUV[0] = 0.0f;
pUV[1] = 0.0f;
pUV = VtxT1.GetPtrTexCrd(0, iCoordSet);
pUV[0] = SPRITETEXCOORDMAX;
pUV[1] = 0.0f;
pUV = VtxT2.GetPtrTexCrd(0, iCoordSet);
pUV[0] = 0.0f;
pUV[1] = SPRITETEXCOORDMAX;
pUV = VtxT3.GetPtrTexCrd(0, iCoordSet);
pUV[0] = SPRITETEXCOORDMAX;
pUV[1] = SPRITETEXCOORDMAX;
}
}
}
}
RRCLIPCODE clipIntersection, clipUnion;
RRCLIPCODE c[4];
RRFVFExtractor* pVtxTs[4] = {&VtxT0, &VtxT1, &VtxT2, &VtxT3};
for ( INT32 i= 0; i < 4; i++)
{
FLOAT x_clip = pVtxTs[i]->GetX();
FLOAT y_clip = pVtxTs[i]->GetY();
FLOAT z_clip = pVtxTs[i]->GetZ();
FLOAT w_clip = pVtxTs[i]->GetRHW();
c[i] = ComputeClipCodes(&clipIntersection, &clipUnion, x_clip, y_clip,
z_clip, w_clip, 0.0f);
if (c[i] == 0 || ((m_dwTLState & RRPV_GUARDBAND) && ((c[i] & ~RRCLIP_INGUARDBAND) == 0)))
{
// need to compute screen coordinates
FLOAT inv_w_clip = 1.0f/w_clip;
FLOAT *pXYZW = pVtxTs[i]->GetPtrXYZ();
pXYZW[0] = x_clip * inv_w_clip * m_ViewData.scaleX +
m_ViewData.offsetX;
pXYZW[1] = y_clip * inv_w_clip * m_ViewData.scaleY +
m_ViewData.offsetY;
pXYZW[2] = z_clip * inv_w_clip * m_ViewData.scaleZ +
m_ViewData.offsetZ;
pXYZW[3] = inv_w_clip;
}
}
// set point sprite mode in rasterizer
m_bPointSprite = TRUE;
DrawClippedTriangle(pvVT0, c[0], pvVT1, c[1], pvVT2, c[2], 0);
DrawClippedTriangle(pvVT1, c[1], pvVT3, c[3], pvVT2, c[2], 0);
// clear point sprite mode in rasterizer
m_bPointSprite = FALSE;
m_qwFVFControl = qwFVFControlSave;
m_dwOutputVtxSize = dwOutputVtxSizeSave;
m_qwFVFOut = qwFVFOutSave;
m_dwTextureCoordSizeTotal = dwTextureCoordSizeTotalSave;
memcpy(m_dwTexCoordSize, dwTexCoordSizeSave, sizeof(DWORD)*D3DDP_MAXTEXCOORD);
m_clipping.dwInterpolate = dwInterpolateSave;
m_dwNumTexCoords = dwNumTexCoordsSave;
MEMFREE( pvVT0 );
MEMFREE( pvVT1 );
MEMFREE( pvVT2 );
MEMFREE( pvVT3 );
}
else
{
// Just x y clipped. Let bounding box handle it
DrawPoint( pvV0, pvVFlat );
}
#endif
}
}
////////////////////////////////////////////////////////////////////////////
//
// Returns 0, if triangle is clipped. Number of vertices otherwise.
//
// Original vertices should not be modified inside the function
////////////////////////////////////////////////////////////////////////////
#undef DPF_MODNAME
#define DPF_MODNAME "ClipSingleTriangle"
int
ReferenceRasterizer::ClipSingleTriangle(RRCLIPTRIANGLE *tri,
RRCLIPVTX ***clipVertexPointer)
{
int accept;
int i, j;
int count;
RRCLIPVTX **inv;
RRCLIPVTX **outv;
RRCLIPVTX *p;
ULONG_PTR swapv;
D3DCOLOR diffuse1; // Original colors
D3DCOLOR specular1;
D3DCOLOR diffuse2;
D3DCOLOR specular2;
DWORD dwClipBit;
DWORD dwClippedBit;
if (GetRenderState()[D3DRENDERSTATE_SHADEMODE] == D3DSHADE_FLAT)
{
// It is easier to set all vertices to the same color here
D3DCOLOR diffuse = tri->v[0]->color;
D3DCOLOR specular = tri->v[0]->specular;
//Save original colors
diffuse1 = tri->v[1]->color;
specular1 = tri->v[1]->specular;
diffuse2 = tri->v[2]->color;
specular2 = tri->v[2]->specular;
// copy all but fog intensity
tri->v[1]->color= diffuse;
tri->v[1]->specular &= 0xFF000000; tri->v[1]->specular |= (0x00FFFFFF & specular);
tri->v[2]->color = diffuse;
tri->v[2]->specular &= 0xFF000000; tri->v[2]->specular |= (0x00FFFFFF & specular);
}
accept = (tri->v[0]->clip | tri->v[1]->clip | tri->v[2]->clip);
inv = tri->v;
count = 3;
outv = m_clipping.clip_vbuf1;
m_clipping.clip_color = tri->v[0]->color;
m_clipping.clip_specular = tri->v[0]->specular;
/*
* XXX assumes sizeof(void*) == sizeof(unsigned long)
*/
{
ULONG_PTR tmp1;
ULONG_PTR tmp2;
tmp1 = (ULONG_PTR)m_clipping.clip_vbuf1;
tmp2 = (ULONG_PTR)m_clipping.clip_vbuf2;
swapv = tmp1 + tmp2;
}
m_clipping.clip_vertices_used = 0;
#define SWAP(inv, outv) \
inv = outv; \
outv = (RRCLIPVTX**) (swapv - (ULONG_PTR) outv)
if (accept & RRCLIP_FRONT)
{
count = ClipFront( inv, outv, count );
if (count < 3)
goto out_of_here;
SWAP(inv, outv);
}
if (m_dwTLState & RRPV_GUARDBAND)
{
// If there was clipping by the front plane it is better to
// compute clip code for new vertices and re-compute accept.
// Otherwise we will try to clip by sides when it is not necessary
if (accept & RRCLIP_FRONT)
{
accept = 0;
for (i = 0; i < count; i++)
{
RRCLIPVTX *p;
p = inv[i];
if (p->clip & CLIPPED_FRONT)
accept |= ComputeClipCodeGB(m_ViewData,
m_xfmUserClipPlanes, p);
else
accept |= p->clip;
}
}
if (accept & RRCLIP_BACK)
{
count = ClipBack( inv, outv, count );
if (count < 3)
goto out_of_here;
SWAP(inv, outv);
}
if (accept & RRCLIPGB_LEFT)
{
count = ClipLeftGB( inv, outv, count );
if (count < 3)
goto out_of_here;
SWAP(inv, outv);
}
if (accept & RRCLIPGB_RIGHT)
{
count = ClipRightGB( inv, outv, count );
if (count < 3)
goto out_of_here;
SWAP(inv, outv);
}
if (accept & RRCLIPGB_BOTTOM)
{
count = ClipBottomGB( inv, outv, count );
if (count < 3)
goto out_of_here;
SWAP(inv, outv);
}
if (accept & RRCLIPGB_TOP)
{
count = ClipTopGB( inv, outv, count );
if (count < 3)
goto out_of_here;
SWAP(inv, outv);
}
}
else
{
// If there was clipping by the front plane it is better to
// compute clip code for new vertices and re-compute accept.
// Otherwise we will try to clip by sides when it is not necessary
if (accept & RRCLIP_FRONT)
{
accept = 0;
for (i = 0; i < count; i++)
{
RRCLIPVTX *p;
p = inv[i];
if (p->clip & (CLIPPED_FRONT))
accept |= ComputeClipCode( m_xfmUserClipPlanes, p );
else
accept |= p->clip;
}
}
if (accept & RRCLIP_BACK)
{
count = ClipBack( inv, outv, count );
if (count < 3)
goto out_of_here;
SWAP(inv, outv);
}
if (accept & RRCLIP_LEFT)
{
count = ClipLeft( inv, outv, count );
if (count < 3)
goto out_of_here;
SWAP(inv, outv);
}
if (accept & RRCLIP_RIGHT)
{
count = ClipRight( inv, outv, count );
if (count < 3)
goto out_of_here;
SWAP(inv, outv);
}
if (accept & RRCLIP_BOTTOM)
{
count = ClipBottom( inv, outv, count );
if (count < 3)
goto out_of_here;
SWAP(inv, outv);
}
if (accept & RRCLIP_TOP)
{
count = ClipTop( inv, outv, count );
if (count < 3)
goto out_of_here;
SWAP(inv, outv);
}
}
dwClipBit = RRCLIP_USERCLIPPLANE0;
dwClippedBit = CLIPPED_USERCLIPPLANE0;
// User Clip Planes
for( j=0; j<RRMAX_USER_CLIPPLANES; j++)
{
if (accept & dwClipBit)
{
count = ClipByPlane( inv, outv, &m_xfmUserClipPlanes[j].plane,
dwClippedBit, count);
if (count < 3)
goto out_of_here;
SWAP(inv, outv);
}
dwClipBit <<= 1;
dwClippedBit <<= 1;
}
#undef SWAP
ComputeScreenCoordinates( m_ViewData, inv, count );
*clipVertexPointer = inv;
m_clipping.current_vbuf = inv;
return count;
out_of_here:
*clipVertexPointer = NULL;
return 0;
}
//-----------------------------------------------------------------------
//
int
ReferenceRasterizer::ClipSingleLine( RRCLIPTRIANGLE *line )
{
int accept;
int j;
D3DVALUE in1, in2;
DWORD dwClipBit;
DWORD dwClippedBit;
accept = (line->v[0]->clip | line->v[1]->clip);
m_clipping.clip_color = line->v[0]->color;
m_clipping.clip_specular = line->v[0]->specular;
if (accept & D3DCLIP_FRONT)
if (ClipLineFront(line))
goto out_of_here;
if (m_dwTLState & RRPV_GUARDBAND)
{
// If there was clipping by the front plane it is better to
// compute clip code for new vertices and re-compute accept.
// Otherwise we will try to clip by sides when it is not necessary
if (accept & D3DCLIP_FRONT)
{
RRCLIPVTX * p;
accept = 0;
p = line->v[0];
if (p->clip & CLIPPED_FRONT)
accept |= ComputeClipCodeGB(m_ViewData, m_xfmUserClipPlanes, p);
else
accept |= p->clip;
p = line->v[1];
if (p->clip & CLIPPED_FRONT)
accept |= ComputeClipCodeGB(m_ViewData, m_xfmUserClipPlanes, p);
else
accept |= p->clip;
}
if (accept & D3DCLIP_BACK)
if (ClipLineBack( line ))
goto out_of_here;
if (accept & RRCLIPGB_LEFT)
if (ClipLineLeftGB( line ))
goto out_of_here;
if (accept & RRCLIPGB_RIGHT)
if (ClipLineRightGB( line ))
goto out_of_here;
if (accept & RRCLIPGB_TOP)
if (ClipLineTopGB( line ))
goto out_of_here;
if (accept & RRCLIPGB_BOTTOM)
if (ClipLineBottomGB( line ))
goto out_of_here;
}
else
{
// If there was clipping by the front plane it is better to
// compute clip code for new vertices and re-compute accept.
// Otherwise we will try to clip by sides when it is not necessary
if (accept & D3DCLIP_FRONT)
{
RRCLIPVTX * p;
accept = 0;
p = line->v[0];
if (p->clip & CLIPPED_FRONT)
accept |= ComputeClipCode( m_xfmUserClipPlanes, p );
else
accept |= p->clip;
p = line->v[1];
if (p->clip & CLIPPED_FRONT)
accept |= ComputeClipCode( m_xfmUserClipPlanes, p );
else
accept |= p->clip;
}
if (accept & D3DCLIP_BACK)
if (ClipLineBack( line ))
goto out_of_here;
if (accept & D3DCLIP_LEFT)
if (ClipLineLeft( line ))
goto out_of_here;
if (accept & D3DCLIP_RIGHT)
if (ClipLineRight( line ))
goto out_of_here;
if (accept & D3DCLIP_TOP)
if (ClipLineTop( line ))
goto out_of_here;
if (accept & D3DCLIP_BOTTOM)
if (ClipLineBottom( line ))
goto out_of_here;
}
// User Clip Planes
dwClipBit = RRCLIP_USERCLIPPLANE0;
dwClippedBit = CLIPPED_USERCLIPPLANE0;
for( j=0; j<RRMAX_USER_CLIPPLANES; j++)
{
if (accept & dwClipBit)
{
if( ClipLineByPlane( line, &m_xfmUserClipPlanes[j].plane,
dwClippedBit ))
goto out_of_here;
}
dwClipBit <<= 1;
dwClippedBit <<= 1;
}
ComputeScreenCoordinates(m_ViewData, line->v, 2);
return 1;
out_of_here:
return 0;
}