|
|
#include "pch.cpp"
#pragma hdrstop
#define GET_NEW_CLIP_VERTEX \
&clip_vertices[clip_vertices_used++];
//---------------------------------------------------------------------
inline void InterpolateColor(RDClipVertex *out, RDClipVertex *p1, RDClipVertex *p2, D3DVALUE num_denom ) { FLOAT r1, g1, b1, a1; FLOAT r2, g2, b2, a2;
r1 = p1->m_diffuse.r; g1 = p1->m_diffuse.g; b1 = p1->m_diffuse.b; a1 = p1->m_diffuse.a; r2 = p2->m_diffuse.r; g2 = p2->m_diffuse.g; b2 = p2->m_diffuse.b; a2 = p2->m_diffuse.a; out->m_diffuse.r = (r1 + (r2 - r1) * num_denom); out->m_diffuse.g = (g1 + (g2 - g1) * num_denom); out->m_diffuse.b = (b1 + (b2 - b1) * num_denom); out->m_diffuse.a = (a1 + (a2 - a1) * num_denom); } //---------------------------------------------------------------------
inline void InterpolateSpecular(RDClipVertex *out, RDClipVertex *p1, RDClipVertex *p2, D3DVALUE num_denom ) { FLOAT r1, g1, b1, a1; FLOAT r2, g2, b2, a2;
r1 = p1->m_specular.r; g1 = p1->m_specular.g; b1 = p1->m_specular.b; a1 = p1->m_specular.a; r2 = p2->m_specular.r; g2 = p2->m_specular.g; b2 = p2->m_specular.b; a2 = p2->m_specular.a; out->m_specular.r = (r1 + (r2 - r1) * num_denom); out->m_specular.g = (g1 + (g2 - g1) * num_denom); out->m_specular.b = (b1 + (b2 - b1) * num_denom); out->m_specular.a = (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; } }
//////////////////////////////////////////////////////////////////////////////
//
// RefClipper implementation
//
//////////////////////////////////////////////////////////////////////////////
const DWORD RefClipper::RCLIP_DIRTY_ZRANGE = (1 << 0); const DWORD RefClipper::RCLIP_DIRTY_VIEWRECT = (1 << 1); const DWORD RefClipper::RCLIP_DO_FLATSHADING = (1 << 2); const DWORD RefClipper::RCLIP_DO_WIREFRAME = (1 << 3); const DWORD RefClipper::RCLIP_DO_ADJUSTWRAP = (1 << 4); const DWORD RefClipper::RCLIP_Z_ENABLE = (1 << 5);
RefClipper::RefClipper() { m_dwFlags = 0; memset( &m_Viewport, 0, sizeof( m_Viewport) );
dvX = dvY = dvWidth = dvHeight = 0.0f; scaleX = scaleY = scaleZ = 0.0f; offsetX = offsetY = offsetZ = 0.0f; scaleXi = scaleYi = scaleZi = 0.0f; minX = minY = maxX = maxY = 0.0f; minXgb = minYgb = maxXgb = maxYgb = 0.0f; gb11 = gb22 = gb41 = gb42 = 0.0f; Kgbx1 = Kgby1 = Kgbx2 = Kgby2 = 0.0f;
memset( clip_vbuf1, 0, sizeof(RDClipVertex*)*RD_MAX_CLIP_VERTICES ); memset( clip_vbuf2, 0, sizeof(RDClipVertex*)*RD_MAX_CLIP_VERTICES ); current_vbuf = 0; memset( clip_vertices, 0, sizeof(RDClipVertex)*RD_MAX_CLIP_VERTICES ); m_dwInterpolate = 0; clip_vertices_used = 0;
m_clipUnion = 0; m_clipIntersection = 0;
// By default enable Guardband and set the extents equal
// to the default RefRast parameters
m_bUseGB = TRUE; minXgb = (RD_GB_LEFT); maxXgb = RD_GB_RIGHT; minYgb = (RD_GB_TOP); maxYgb = RD_GB_BOTTOM;
memset( m_userClipPlanes, 0, sizeof(RDVECTOR4)*RD_MAX_USER_CLIPPLANES );
#if DBG
DWORD v = 0; // Guardband parameters
if( GetD3DRegValue(REG_DWORD, "DisableGB", &v, 4) && v != 0 ) { m_bUseGB = FALSE; } // Try to get test values for the guard band
char value[80]; if( GetD3DRegValue(REG_SZ, "GuardBandLeft", &value, 80) && value[0] != 0 ) sscanf(value, "%f", &minXgb); if( GetD3DRegValue(REG_SZ, "GuardBandRight", &value, 80) && value[0] != 0 ) sscanf(value, "%f", &maxXgb); if( GetD3DRegValue(REG_SZ, "GuardBandTop", &value, 80) && value[0] != 0 ) sscanf(value, "%f", &minYgb); if( GetD3DRegValue(REG_SZ, "GuardBandBottom", &value, 80) && value[0] != 0 ) sscanf(value, "%f", &maxYgb); #endif // DBG
}
//---------------------------------------------------------------------
// RefClipper::UpdateViewData
// Updates View data used by ProcessVertices[VVM]
//---------------------------------------------------------------------
HRESULT RefClipper::UpdateViewData() { HRESULT hr = D3D_OK;
// Update viewport information
if( m_dwFlags & RCLIP_DIRTY_ZRANGE ) { scaleZ = m_Viewport.dvMaxZ - m_Viewport.dvMinZ; offsetZ = m_Viewport.dvMinZ; // ATTENTION: This could be a Divide by Zero here if
// the dvMaxZ == dvMinZ. Fix it later.
scaleZi = D3DVAL(1) / scaleZ; }
if( m_dwFlags & RCLIP_DIRTY_VIEWRECT ) { // Bail if we are going to cause any divide by zero exceptions.
// The likely reason is that we have a bogus viewport set by
// TLVertex execute buffer app.
if(m_Viewport.dwWidth == 0 || m_Viewport.dwHeight == 0 ) return DDERR_GENERIC;
dvX = D3DVAL(m_Viewport.dwX); dvY = D3DVAL(m_Viewport.dwY); dvWidth = D3DVAL(m_Viewport.dwWidth); dvHeight = D3DVAL(m_Viewport.dwHeight);
// Coefficients to compute screen coordinates from normalized window
// coordinates
scaleX = dvWidth; scaleY = - dvHeight; offsetX = dvX; offsetY = dvY + dvHeight;
#if 0
// Small offset is added to prevent generation of negative screen
// coordinates (this could happen because of precision errors).
// Not needed (or wanted) for devices which do guardband.
offsetX += SMALL_NUMBER; offsetY += SMALL_NUMBER; #endif
scaleXi = D3DVAL(1) / scaleX; scaleYi = D3DVAL(1) / scaleY;
minX = dvX; maxX = dvX + dvWidth; minY = dvY; maxY = dvY + dvHeight;
if( m_bUseGB ) { // Because we clip by guard band window we have to use its extents
D3DVALUE w = 2.0f / dvWidth; D3DVALUE h = 2.0f / dvHeight; D3DVALUE ax1 = -(minXgb - dvX) * w + 1.0f; D3DVALUE ax2 = (maxXgb - dvX) * w - 1.0f; D3DVALUE ay1 = (maxYgb - dvY) * h - 1.0f; D3DVALUE ay2 = -(minYgb - dvY) * h + 1.0f; gb11 = 2.0f / (ax1 + ax2); gb41 = gb11 * (ax1 - 1.0f) * 0.5f; gb22 = 2.0f / (ay1 + ay2); gb42 = gb22 * (ay1 - 1.0f) * 0.5f;
Kgbx1 = 0.5f * (1.0f - ax1); Kgbx2 = 0.5f * (1.0f + ax2); Kgby1 = 0.5f * (1.0f - ay1); Kgby2 = 0.5f * (1.0f + ay2); } else { minXgb = minX; maxXgb = maxX; minYgb = minY; maxYgb = maxY; } }
// Clear the dirty transform flags
m_dwFlags &= ~(RCLIP_DIRTY_VIEWRECT | RCLIP_DIRTY_ZRANGE); return hr; }
//---------------------------------------------------------------------
// Make clip vertex from RDVertex
//
// cv - clipVertex
// v - a TL vertex
// qwFVF - FVF of the input TL vertex
//---------------------------------------------------------------------
void RefClipper::MakeClipVertexFromVertex( RDClipVertex& cv, RDVertex& v, DWORD dwClipMask ) { DWORD dwClipFlag = (DWORD) v.m_clip;
memcpy( &cv, &v, sizeof( RDVertex ) );
// If the clip flag for this vertex is set, that means that the
// transformation loop has not computed the screen coordinates for
// this vertex, it has simply stored the clip coordinates for this
// vertex
#if 0
if( v.m_clip & dwClipMask ) { // This is a clipped vertex, simply no screen coordinates
cv.m_pos.x = D3DVALUE(0); cv.m_pos.y = D3DVALUE(0); cv.m_pos.z = D3DVALUE(0); cv.m_rhw = D3DVALUE(0);
// Since this vertex has been clipped, the transformation loop
// has put in the clip coordinates instead
cv.hx = v.m_pos.x; cv.hy = v.m_pos.y; cv.hz = v.m_pos.z; cv.hw = v.m_rhw; } else { // This vertex is not clipped, so its screen coordinates have been
// computed
// Transform the screen coordinate back to the clipping space
cv.hw = 1.0f / cv.m_rhw; cv.hx = (cv.m_pos.x - offsetX) * cv.hw * scaleXi; cv.hy = (cv.m_pos.y - offsetY) * cv.hw * scaleYi; cv.hz = (cv.m_pos.z - offsetZ) * cv.hw * scaleZi;
} #endif
}
//---------------------------------------------------------------------
// RefVP::ComputeClipCodes
//---------------------------------------------------------------------
RDCLIPCODE RefClipper::ComputeClipCodes(RDCLIPCODE* pclipIntersection, RDCLIPCODE* pclipUnion, FLOAT x_clip, FLOAT y_clip, FLOAT z_clip, FLOAT w_clip) { D3DVALUE xx = w_clip - x_clip; D3DVALUE yy = w_clip - y_clip; D3DVALUE zz = w_clip - z_clip;
// if( x < 0 ) clip |= RDCLIP_LEFTBIT;
// if( x >= we ) clip |= RDCLIP_RIGHTBIT;
// if( y < 0 ) clip |= RDCLIP_BOTTOMBIT;
// if( y >= we ) clip |= RDCLIP_TOPBIT;
// if( z < 0 ) clip |= RDCLIP_FRONTBIT;
// if( z >= we ) clip |= RDCLIP_BACKBIT;
RDCLIPCODE clip = ((AS_INT32(x_clip) & 0x80000000) >> (32-RDCLIP_LEFTBIT)) | ((AS_INT32(y_clip) & 0x80000000) >> (32-RDCLIP_BOTTOMBIT))| ((AS_INT32(z_clip) & 0x80000000) >> (32-RDCLIP_FRONTBIT)) | ((AS_INT32(xx) & 0x80000000) >> (32-RDCLIP_RIGHTBIT)) | ((AS_INT32(yy) & 0x80000000) >> (32-RDCLIP_TOPBIT)) | ((AS_INT32(zz) & 0x80000000) >> (32-RDCLIP_BACKBIT));
RDCLIPCODE clipBit = RDCLIP_USERCLIPPLANE0; for( DWORD j=0; j<RD_MAX_USER_CLIPPLANES; j++) { if( m_xfmUserClipPlanes[j].bActive ) { RDVECTOR4& plane = m_xfmUserClipPlanes[j].plane; FLOAT fComp = 0.0f; 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_bUseGB ) { // We do guardband check in the projection space, so
// we transform X and Y of the vertex there
D3DVALUE xnew = x_clip * gb11 + w_clip * gb41; D3DVALUE ynew = y_clip * gb22 + w_clip * gb42; D3DVALUE xx = w_clip - xnew; D3DVALUE yy = w_clip - ynew; clip |= ((AS_INT32(xnew) & 0x80000000) >> (32-RDCLIPGB_LEFTBIT)) | ((AS_INT32(ynew) & 0x80000000) >> (32-RDCLIPGB_BOTTOMBIT)) | ((AS_INT32(xx) & 0x80000000) >> (32-RDCLIPGB_RIGHTBIT)) | ((AS_INT32(yy) & 0x80000000) >> (32-RDCLIPGB_TOPBIT)); } *pclipIntersection &= clip; *pclipUnion |= clip; return clip; } }
//---------------------------------------------------------------------
// RefVP::ComputeClipCodesTL
//---------------------------------------------------------------------
void RefClipper::ComputeClipCodesTL( RDVertex* pVtx ) { FLOAT x, y, z; DWORD clip = 0;
_ASSERT( FVF_TRANSFORMED( pVtx->m_qwFVF ), "Can compute clipcodes only for Transformed vertices." ); DWORD clipZF = (m_dwFlags & RCLIP_Z_ENABLE) ? RDCLIP_FRONT : 0; DWORD clipZB = (m_dwFlags & RCLIP_Z_ENABLE) ? RDCLIP_BACK : 0;
// Invert to compenstate for the sign during the
// divide by w.
if( pVtx->m_rhw < 0 ) { x = -pVtx->m_pos.x; y = -pVtx->m_pos.y; z = -pVtx->m_pos.z; } else { x = pVtx->m_pos.x; y = pVtx->m_pos.y; z = pVtx->m_pos.z; }
if( x < minX ) clip |= RDCLIP_LEFT; else if( x >= maxX ) clip |= RDCLIP_RIGHT;
if (y < minY) clip |= RDCLIP_TOP; else if (y >= maxY) clip |= RDCLIP_BOTTOM;
if (z < 0.0f) clip |= clipZF; else if (z >= 1.0f) clip |= clipZB;
if( m_bUseGB ) { if( x < minXgb ) clip |= RDCLIPGB_LEFT; else if( x >= maxXgb ) clip |= RDCLIPGB_RIGHT;
if( y < minYgb ) clip |= RDCLIPGB_TOP; else if( y >= maxYgb ) clip |= RDCLIPGB_BOTTOM; }
pVtx->m_clip = clip;
// Back transform to obtain the clip-coordinates
pVtx->m_clip_w = 1.0f / pVtx->m_rhw; // This is w_clip
pVtx->m_clip_x = (pVtx->m_pos.x - offsetX) * pVtx->m_clip_w * scaleXi; pVtx->m_clip_y = (pVtx->m_pos.y - offsetY) * pVtx->m_clip_w * scaleYi; pVtx->m_clip_z = (pVtx->m_pos.z - offsetZ) * pVtx->m_clip_w * scaleZi;
return; }
//---------------------------------------------------------------------
// Clipping a triangle by a plane
//
// Returns number of vertices in the clipped triangle
//---------------------------------------------------------------------
int RefClipper::ClipByPlane( RDClipVertex **inv, RDClipVertex **outv, RDVECTOR4 *plane, DWORD dwClipFlag, int count ) { int i; int out_count = 0; RDClipVertex *curr, *prev; D3DVALUE curr_inside; D3DVALUE prev_inside;
prev = inv[count-1]; curr = *inv++; prev_inside = prev->m_clip_x*plane->x + prev->m_clip_y*plane->y + prev->m_clip_z*plane->z + prev->m_clip_w*plane->w; for (i = count; i; i--) { curr_inside = curr->m_clip_x*plane->x + curr->m_clip_y*plane->y + curr->m_clip_z*plane->z + curr->m_clip_w*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; outv[out_count]->m_qwFVF = prev->m_qwFVF; Interpolate( outv[out_count], curr, prev, (prev->m_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; outv[out_count]->m_qwFVF = prev->m_qwFVF; 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 RefClipper::ClipLineByPlane( RDCLIPTRIANGLE *line, RDVECTOR4 *plane, DWORD dwClipBit ) { D3DVALUE in1, in2; RDClipVertex outv; in1 = line->v[0]->m_clip_x * plane->x + line->v[0]->m_clip_y * plane->y + line->v[0]->m_clip_z * plane->z + line->v[0]->m_clip_w * plane->w; in2 = line->v[1]->m_clip_x * plane->x + line->v[1]->m_clip_y * plane->y + line->v[1]->m_clip_z * plane->z + line->v[1]->m_clip_w * 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 RefClipper::ComputeScreenCoordinates( RDClipVertex **inv, int count ) { int i;
for (i = 0; i < count; i++) { RDClipVertex *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->m_clip & ~CLIPPED_ENABLE ) { D3DVALUE inv_w;
inv_w = D3DVAL(1.0)/p->m_clip_w; switch ((int)p->m_clip & (CLIPPED_LEFT|CLIPPED_RIGHT)) { case CLIPPED_LEFT: p->m_pos.x = minXgb; break; case CLIPPED_RIGHT: p->m_pos.x = maxXgb; break; default: p->m_pos.x = p->m_clip_x * scaleX * inv_w + offsetX; if( p->m_pos.x < minXgb ) p->m_pos.x = minXgb; if( p->m_pos.x > maxXgb ) p->m_pos.x = maxXgb; } switch ((int)p->m_clip & (CLIPPED_TOP|CLIPPED_BOTTOM)) { case CLIPPED_BOTTOM: p->m_pos.y = maxYgb; break; case CLIPPED_TOP: p->m_pos.y = minYgb; break; default: p->m_pos.y = p->m_clip_y * scaleY * inv_w + offsetY; if( p->m_pos.y < minYgb ) p->m_pos.y = minYgb; if( p->m_pos.y > maxYgb ) p->m_pos.y = maxYgb; } p->m_pos.z = p->m_clip_z * scaleZ * inv_w + offsetZ; p->m_rhw = inv_w; } } } //---------------------------------------------------------------------
void RefClipper::Interpolate( RDClipVertex *out, RDClipVertex *p1, RDClipVertex *p2, int code, D3DVALUE num, D3DVALUE denom ) { DWORD dwInterpolate = m_dwInterpolate; D3DVALUE num_denom = num / denom;
out->m_clip = (((int)p1->m_clip & (int)p2->m_clip) & ~CLIPPED_ENABLE) | code; out->m_clip_x = p1->m_clip_x + (p2->m_clip_x - p1->m_clip_x) * num_denom; out->m_clip_y = p1->m_clip_y + (p2->m_clip_y - p1->m_clip_y) * num_denom; out->m_clip_z = p1->m_clip_z + (p2->m_clip_z - p1->m_clip_z) * num_denom; out->m_clip_w = p1->m_clip_w + (p2->m_clip_w - p1->m_clip_w) * num_denom; out->m_diffuse = clip_color; out->m_specular = clip_specular;
/*
* Interpolate any other color model or quality dependent values. */ if( dwInterpolate & RDCLIP_INTERPOLATE_COLOR ) { InterpolateColor(out, p1, p2, num_denom); }
if( dwInterpolate & RDCLIP_INTERPOLATE_SPECULAR ) { InterpolateSpecular(out, p1, p2, num_denom); }
if( dwInterpolate & RDCLIP_INTERPOLATE_TEXTURE ) { UINT64 qwFVF = p1->m_qwFVF;
// Assume that D3DRENDERSTATE_WRAPi are sequential
DWORD numTex = FVF_TEXCOORD_NUMBER(qwFVF); for (DWORD i = 0; i < numTex; i++) { FLOAT* pTexture1 = (FLOAT *)&p1->m_tex[i]; FLOAT* pTexture2 = (FLOAT *)&p2->m_tex[i]; FLOAT* pTexture = (FLOAT *)&out->m_tex[i]; DWORD wrapState;
if( m_dwFlags & RCLIP_DO_ADJUSTWRAP ) { DWORD TCI = m_pDev->GetTSS(i)[D3DTSS_TEXCOORDINDEX] & 0xffff; wrapState = m_pDev->GetRS()[D3DRENDERSTATE_WRAP0 + TCI]; } else { wrapState = m_pDev->GetRS()[D3DRENDERSTATE_WRAP0 + i]; }
DWORD n = GetTexCoordDim(qwFVF, i); // DWORD n = (DWORD)(m_dwTexCoordSizeArray[i] >> 2);
DWORD dwWrapBit = 1; for (DWORD j=0; j < n; j++) { pTexture[j] = InterpolateTexture(pTexture1[j], pTexture2[j], num_denom, wrapState & dwWrapBit); dwWrapBit <<= 1; } } } if( dwInterpolate & RDCLIP_INTERPOLATE_S ) { out->m_pointsize = p1->m_pointsize + (p2->m_pointsize - p1->m_pointsize) * num_denom; } if( dwInterpolate & RDCLIP_INTERPOLATE_FOG ) { out->m_fog = p1->m_fog + (p2->m_fog - p1->m_fog) * 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 m_clip_x
#include "clip.h"
#define __CLIP_NAME ClipRight
#define __CLIP_LINE_NAME ClipLineRight
#define __CLIP_W
#define __CLIP_FLAG CLIPPED_RIGHT
#define __CLIP_COORD m_clip_x
#include "clip.h"
#define __CLIP_NAME ClipBottom
#define __CLIP_LINE_NAME ClipLineBottom
#define __CLIP_FLAG CLIPPED_BOTTOM
#define __CLIP_COORD m_clip_y
#include "clip.h"
#define __CLIP_NAME ClipTop
#define __CLIP_LINE_NAME ClipLineTop
#define __CLIP_W
#define __CLIP_FLAG CLIPPED_TOP
#define __CLIP_COORD m_clip_y
#include "clip.h"
#define __CLIP_NAME ClipBack
#define __CLIP_LINE_NAME ClipLineBack
#define __CLIP_W
#define __CLIP_FLAG CLIPPED_BACK
#define __CLIP_COORD m_clip_z
#include "clip.h"
#define __CLIP_NAME ClipFront
#define __CLIP_LINE_NAME ClipLineFront
#define __CLIP_FLAG CLIPPED_FRONT
#define __CLIP_COORD m_clip_z
#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 m_clip_x
#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 m_clip_x
#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 m_clip_y
#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 m_clip_y
#define __CLIP_GBCOEF Kgby2
#define __CLIP_SIGN +
#include "clip.h"
#undef __CLIP_GUARDBAND
//---------------------------------------------------------------------
inline DWORD ComputeClipCodeUserPlanes( RDUSERCLIPPLANE *UserPlanes, RDClipVertex *p) { DWORD clip = 0; DWORD dwClipBit = RDCLIP_USERCLIPPLANE0; for( DWORD j=0; j<RD_MAX_USER_CLIPPLANES; j++) { if( UserPlanes[j].bActive ) { RDVECTOR4& plane = UserPlanes[j].plane; if( (p->m_clip_x*plane.x + p->m_clip_y*plane.y + p->m_clip_z*plane.z + p->m_clip_w*plane.w) < 0 ) { clip |= dwClipBit; } } dwClipBit <<= 1; } return clip; }
//---------------------------------------------------------------------
inline DWORD RefClipper::ComputeClipCodeGB( RDClipVertex *p ) { DWORD clip = 0; if( p->m_clip_x < p->m_clip_w * Kgbx1 ) clip |= RDCLIPGB_LEFT; if( p->m_clip_x > p->m_clip_w * Kgbx2 ) clip |= RDCLIPGB_RIGHT; if( p->m_clip_y < p->m_clip_w * Kgby1 ) clip |= RDCLIPGB_BOTTOM; if( p->m_clip_y > p->m_clip_w * Kgby2 ) clip |= RDCLIPGB_TOP; if( p->m_clip_z > p->m_clip_w ) clip |= RDCLIP_BACK; clip |= ComputeClipCodeUserPlanes( m_xfmUserClipPlanes, p ); p->m_clip = (p->m_clip & (CLIPPED_ENABLE | CLIPPED_FRONT)) | clip; return clip; }
//---------------------------------------------------------------------
inline DWORD RefClipper::ComputeClipCode( RDClipVertex *p ) { DWORD clip = 0; if( FLOAT_LTZ(p->m_clip_x) ) clip |= RDCLIP_LEFT; if( p->m_clip_x > p->m_clip_w ) clip |= RDCLIP_RIGHT; if( FLOAT_LTZ(p->m_clip_y) ) clip |= RDCLIP_BOTTOM; if( p->m_clip_y > p->m_clip_w ) clip |= RDCLIP_TOP; if( p->m_clip_z > p->m_clip_w ) clip |= RDCLIP_BACK; clip |= ComputeClipCodeUserPlanes( m_xfmUserClipPlanes, p ); p->m_clip = (p->m_clip & (CLIPPED_ENABLE | CLIPPED_FRONT)) | clip; return clip; }
//---------------------------------------------------------------------
// RefDev::UpdateClipper
// Updates clipping data used by ProcessVertices
// BOOL bProgrammablePipeLine: If this is true, it means that the
// programmable vertex machine is invoking
// this method.
//---------------------------------------------------------------------
HRESULT RefDev::UpdateClipper() { HRESULT hr = D3D_OK;
HR_RET( m_Clipper.UpdateViewData() ); DWORD dwClipPlanesEnable = GetRS()[D3DRENDERSTATE_CLIPPLANEENABLE];
if( !GetRS()[D3DRENDERSTATE_CLIPPING] ) return S_OK;
m_Clipper.m_dwFlags &= ~RefClipper::RCLIP_DO_ADJUSTWRAP; if( (m_RefVP.m_dwTLState & (RDPV_DOTEXXFORM | RDPV_DOTEXGEN)) && m_pCurrentVShader->IsFixedFunction() ) m_Clipper.m_dwFlags |= RefClipper::RCLIP_DO_ADJUSTWRAP;
// Figure out which pieces need to be interpolated in new vertices.
m_Clipper.m_dwInterpolate = 0; if( GetRS()[D3DRENDERSTATE_SHADEMODE] == D3DSHADE_GOURAUD ) { m_Clipper.m_dwInterpolate |= RDCLIP_INTERPOLATE_COLOR;
if( m_qwFVFOut & D3DFVF_SPECULAR ) { m_Clipper.m_dwInterpolate |= RDCLIP_INTERPOLATE_SPECULAR; } }
// if( GetRS()[D3DRENDERSTATE_FOGENABLE] )
if( m_qwFVFOut & D3DFVFP_FOG ) { m_Clipper.m_dwInterpolate |= RDCLIP_INTERPOLATE_FOG; }
if( FVF_TEXCOORD_NUMBER(m_qwFVFOut) != 0 ) { m_Clipper.m_dwInterpolate |= RDCLIP_INTERPOLATE_TEXTURE; }
if( m_qwFVFOut & D3DFVF_PSIZE ) // m_primType == D3DPT_POINTLIST
{ m_Clipper.m_dwInterpolate |= RDCLIP_INTERPOLATE_S; }
// Clear clip union and intersection flags
m_Clipper.m_clipIntersection = 0; m_Clipper.m_clipUnion = 0;
// The matrix to transform user clip planes depends on whether it is a
// fixed function pipeline or a programmable pipeline.
// Programmable pipeline: the clip-planes are transformed by the
// Inverse(Mshift) to adjust for clipping in the clipper. The user is
// assumed to have pre-transformed the clip-planes to the clipping
// space.
// Fixed function pipeline: the clip-planes are transformed to the clipping
// space by the Inverse(Mview * Mproj * Mshift).
RDMATRIX* pUserClipPlaneMatrix = NULL; RDMATRIX matProgPipe = { 2, 0, 0, 0, 0, 2, 0, 0, 0, 0, 1, 0, -1,-1, 0, 1 }; if( m_pCurrentVShader->IsFixedFunction() ) { pUserClipPlaneMatrix = &(m_RefVP.m_TransformData.m_VPSInv); } else { pUserClipPlaneMatrix = &matProgPipe; }
// Update the user defined clip plane data
for( DWORD i=0; i<RD_MAX_USER_CLIPPLANES; i++ ) { // Figure out if it is active
m_Clipper.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_Clipper.m_xfmUserClipPlanes[i].bActive ) { XformPlaneBy4x4Transposed( &(m_Clipper.m_userClipPlanes[i]), pUserClipPlaneMatrix, &(m_Clipper.m_xfmUserClipPlanes[i].plane) ); } } return hr; }
//----------------------------------------------------------------------------
//
// DrawOnePrimitive
//
// Draw one clipped primitive.
//
//----------------------------------------------------------------------------
HRESULT RefClipper::DrawOnePrimitive( GArrayT<RDVertex>& VtxArray, DWORD dwStartVertex, D3DPRIMITIVETYPE PrimType, UINT cVertices ) { INT i; RDVertex* pV0; RDVertex* pV1; RDVertex* pV2; HRESULT hr; DWORD dwCurrVtx = dwStartVertex;
switch( PrimType ) { case D3DPT_POINTLIST: for (i = 0; i < (INT)cVertices; i++) { DrawPoint(&VtxArray[i]); } break;
case D3DPT_LINELIST: for (i = (INT)cVertices / 2; i > 0; i--) { pV0 = &VtxArray[dwCurrVtx++]; pV1 = &VtxArray[dwCurrVtx++];
DrawLine(pV0, pV1); } break; case D3DPT_LINESTRIP: { pV1 = &VtxArray[dwCurrVtx];
// Disable last-pixel setting for shared verties and store prestate.
m_pDev->StoreLastPixelState(TRUE);
// Initial pV0.
for (i = (INT)cVertices - 1; i > 1; i--) { pV0 = pV1; dwCurrVtx++; pV1 = &VtxArray[dwCurrVtx]; DrawLine(pV0, pV1); }
// Restore last-pixel setting.
m_pDev->StoreLastPixelState(FALSE);
// Draw last line with last-pixel setting from state.
if( i == 1 ) { dwCurrVtx++; pV0 = &VtxArray[dwCurrVtx]; DrawLine(pV1, pV0); } } break;
case D3DPT_TRIANGLELIST: for (i = (INT)cVertices; i > 0; i -= 3) { pV0 = &VtxArray[dwCurrVtx++]; pV1 = &VtxArray[dwCurrVtx++]; pV2 = &VtxArray[dwCurrVtx++];
DrawTriangle(pV0, pV1, pV2); } break; case D3DPT_TRIANGLESTRIP: { // Get initial vertex values.
pV1 = &VtxArray[dwCurrVtx++]; pV2 = &VtxArray[dwCurrVtx++];
for (i = (INT)cVertices - 2; i > 1; i -= 2) { pV0 = pV1; pV1 = pV2; pV2 = &VtxArray[dwCurrVtx++]; DrawTriangle(pV0, pV1, pV2);
pV0 = pV1; pV1 = pV2; pV2 = &VtxArray[dwCurrVtx++]; DrawTriangle(pV0, pV2, pV1); }
if( i > 0 ) { pV0 = pV1; pV1 = pV2; pV2 = &VtxArray[dwCurrVtx]; DrawTriangle(pV0, pV1, pV2); } } break; case D3DPT_TRIANGLEFAN: { RDCLIPCODE c0, c1, c2;
pV2 = &VtxArray[dwCurrVtx++]; // Preload initial pV0.
pV1 = &VtxArray[dwCurrVtx++]; for (i = (INT)cVertices - 2; i > 0; i--) { pV0 = pV1; pV1 = &VtxArray[dwCurrVtx++]; DrawTriangle(pV0, pV1, pV2); } } break;
default: DPFERR("Refrast Error: Unknown or unsupported primitive type " "requested of DrawOnePrimitive"); return DDERR_INVALIDPARAMS; } return D3D_OK; }
//----------------------------------------------------------------------------
//
// DrawOneIndexedPrimitive
//
// Draw one list of clipped indexed primitives.
//
//----------------------------------------------------------------------------
HRESULT RefClipper::DrawOneIndexedPrimitive( GArrayT<RDVertex>& VtxArray, int StartVertexIndex, LPWORD pIndices, DWORD StartIndex, UINT cIndices, D3DPRIMITIVETYPE PrimType ) { INT i; RDVertex* pV0; RDVertex* pV1; RDVertex* pV2; LPWORD puIndices = pIndices + StartIndex; DWORD dwCurrIndex;
HRESULT hr;
switch( PrimType ) { case D3DPT_POINTLIST: for (i = (INT)cIndices; i > 0; i--) { pV0 = &VtxArray[StartVertexIndex + *puIndices++]; DrawPoint( pV0 ); } break;
case D3DPT_LINELIST: for (i = (INT)cIndices / 2; i > 0; i--) { pV0 = &VtxArray[StartVertexIndex + *puIndices++]; pV1 = &VtxArray[StartVertexIndex + *puIndices++]; DrawLine(pV0, pV1); } break; case D3DPT_LINESTRIP: { // Disable last-pixel setting for shared verties and store prestate.
m_pDev->StoreLastPixelState(TRUE); // Initial pV1.
pV1 = &VtxArray[StartVertexIndex + *puIndices++]; for (i = (INT)cIndices - 1; i > 1; i--) { pV0 = pV1; pV1 = &VtxArray[StartVertexIndex + *puIndices++]; DrawLine(pV0, pV1); } // Restore last-pixel setting.
m_pDev->StoreLastPixelState(FALSE);
// Draw last line with last-pixel setting from state.
if( i == 1 ) { pV0 = &VtxArray[StartVertexIndex + *puIndices]; DrawLine(pV1, pV0); } } break;
case D3DPT_TRIANGLELIST: for (i = (INT)cIndices; i > 0; i -= 3) { pV0 = &VtxArray[StartVertexIndex + *puIndices++]; pV1 = &VtxArray[StartVertexIndex + *puIndices++]; pV2 = &VtxArray[StartVertexIndex + *puIndices++]; DrawTriangle(pV0, pV1, pV2); } break; case D3DPT_TRIANGLESTRIP: { // Get initial vertex values.
pV1 = &VtxArray[StartVertexIndex + *puIndices++]; pV2 = &VtxArray[StartVertexIndex + *puIndices++];
for (i = (INT)cIndices - 2; i > 1; i -= 2) { pV0 = pV1; pV1 = pV2; pV2 = &VtxArray[StartVertexIndex + *puIndices++]; DrawTriangle(pV0, pV1, pV2);
pV0 = pV1; pV1 = pV2; pV2 = &VtxArray[StartVertexIndex + *puIndices++]; DrawTriangle(pV0, pV2, pV1); }
if( i > 0 ) { pV0 = pV1; pV1 = pV2; pV2 = &VtxArray[StartVertexIndex + *puIndices++]; DrawTriangle(pV0, pV1, pV2); } } break; case D3DPT_TRIANGLEFAN: { pV2 = &VtxArray[StartVertexIndex + *puIndices++]; // Preload initial pV0.
pV1 = &VtxArray[StartVertexIndex + *puIndices++]; for (i = (INT)cIndices - 2; i > 0; i--) { pV0 = pV1; pV1 = &VtxArray[StartVertexIndex + *puIndices++]; DrawTriangle(pV0, pV1, pV2); } } break;
default: DPFERR("Refrast Error: Unknown or unsupported primitive type " "requested of DrawOneIndexedPrimitive"); return DDERR_INVALIDPARAMS; } return D3D_OK; }
HRESULT RefClipper::DrawOneIndexedPrimitive( GArrayT<RDVertex>& VtxArray, int StartVertexIndex, LPDWORD pIndices, DWORD StartIndex, UINT cIndices, D3DPRIMITIVETYPE PrimType ) { INT i; RDVertex* pV0; RDVertex* pV1; RDVertex* pV2; LPDWORD puIndices = pIndices + StartIndex;
HRESULT hr;
switch( PrimType ) { case D3DPT_POINTLIST: for (i = (INT)cIndices; i > 0; i--) { pV0 = &VtxArray[StartVertexIndex + *puIndices++]; DrawPoint(pV0); } break;
case D3DPT_LINELIST: for (i = (INT)cIndices / 2; i > 0; i--) { pV0 = &VtxArray[StartVertexIndex + *puIndices++]; pV1 = &VtxArray[StartVertexIndex + *puIndices++]; DrawLine(pV0, pV1); } break; case D3DPT_LINESTRIP: { // Disable last-pixel setting for shared verties and store prestate.
m_pDev->StoreLastPixelState(TRUE); // Initial pV1.
pV1 = &VtxArray[StartVertexIndex + *puIndices++]; for (i = (INT)cIndices - 1; i > 1; i--) { pV0 = pV1; pV1 = &VtxArray[StartVertexIndex + *puIndices++]; DrawLine(pV0, pV1); } // Restore last-pixel setting.
m_pDev->StoreLastPixelState(FALSE);
// Draw last line with last-pixel setting from state.
if( i == 1 ) { pV0 = &VtxArray[StartVertexIndex + *puIndices]; DrawLine(pV1, pV0); } } break;
case D3DPT_TRIANGLELIST: for (i = (INT)cIndices; i > 0; i -= 3) { pV0 = &VtxArray[StartVertexIndex + *puIndices++]; pV1 = &VtxArray[StartVertexIndex + *puIndices++]; pV2 = &VtxArray[StartVertexIndex + *puIndices++]; DrawTriangle(pV0, pV1, pV2); } break; case D3DPT_TRIANGLESTRIP: { // Get initial vertex values.
pV1 = &VtxArray[StartVertexIndex + *puIndices++]; pV2 = &VtxArray[StartVertexIndex + *puIndices++];
for (i = (INT)cIndices - 2; i > 1; i -= 2) { pV0 = pV1; pV1 = pV2; pV2 = &VtxArray[StartVertexIndex + *puIndices++]; DrawTriangle(pV0, pV1, pV2);
pV0 = pV1; pV1 = pV2; pV2 = &VtxArray[StartVertexIndex + *puIndices++]; DrawTriangle(pV0, pV2, pV1); }
if( i > 0 ) { pV0 = pV1; pV1 = pV2; pV2 = &VtxArray[StartVertexIndex + *puIndices++]; DrawTriangle(pV0, pV1, pV2); } } break; case D3DPT_TRIANGLEFAN: { pV2 = &VtxArray[StartVertexIndex + *puIndices++]; // Preload initial pV0.
pV1 = &VtxArray[StartVertexIndex + *puIndices++]; for (i = (INT)cIndices - 2; i > 0; i--) { pV0 = pV1; pV1 = &VtxArray[StartVertexIndex + *puIndices++]; DrawTriangle(pV0, pV1, pV2); } } break;
default: DPFERR("Refrast Error: Unknown or unsupported primitive type " "requested of DrawOneIndexedPrimitive"); return DDERR_INVALIDPARAMS; } return D3D_OK; }
///////////////////////////////////////////////////////////////////////////////
//
///////////////////////////////////////////////////////////////////////////////
void RefClipper::DrawTriangle( RDVertex* pV0, RDVertex* pV1, RDVertex* pV2, WORD wFlags ) { // If the clip-codes dont exist then compute them. This happens only
// for Transformed vertices that are directly passed in to be rasterized.
if( (pV0->m_qwFVF & D3DFVFP_CLIP) == 0 ) ComputeClipCodesTL( pV0 ); if( (pV1->m_qwFVF & D3DFVFP_CLIP) == 0 ) ComputeClipCodesTL( pV1 ); if( (pV2->m_qwFVF & D3DFVFP_CLIP) == 0 ) ComputeClipCodesTL( pV2 );
RDCLIPCODE c0 = pV0->m_clip; RDCLIPCODE c1 = pV1->m_clip; RDCLIPCODE c2 = pV2->m_clip;
DWORD dwInter = (c0 & c1 & c2); DWORD dwUnion = (c0 | c1 | c2); DWORD dwMask = (UseGuardBand()) ? RDCLIPGB_ALL : RDCLIP_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 ) { m_pDev->DrawTriangle( pV0, pV1, pV2, wFlags ); return; }
// Do Clipping
RDCLIPTRIANGLE newtri; RDClipVertex cv[3];
MakeClipVertexFromVertex( cv[0], *pV0, dwMask); MakeClipVertexFromVertex( cv[1], *pV1, dwMask); MakeClipVertexFromVertex( cv[2], *pV2, 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; RDClipVertex **ver; cv[0].m_clip |= CLIPPED_ENABLE; cv[1].m_clip |= CLIPPED_ENABLE; cv[2].m_clip |= CLIPPED_ENABLE;
if( count = ClipSingleTriangle( &newtri, &ver ) ) { int i;
// Temporary Byte Array
if( FAILED( ClipBuf.Grow(count) ) ) return;
for (i = 0; i < count; i++) { MakeVertexFromClipVertex( ClipBuf[i], *(ver[i]) ); ClipBuf[i].SetFVF( pV0->m_qwFVF ); }
// If it is in wireframe mode, convert the clipper output to
// a line list.
if( m_dwFlags & RCLIP_DO_WIREFRAME ) { DWORD dwEdgeFlags = 0; for (i = 0; i < count; i++) { if( ver[i]->m_clip & CLIPPED_ENABLE ) dwEdgeFlags |= (1 << i); }
m_pDev->DrawOneEdgeFlagTriangleFan( ClipBuf, count, dwEdgeFlags ); } else { m_pDev->DrawOnePrimitive( ClipBuf, 0, D3DPT_TRIANGLEFAN, count ); } } }
void RefClipper::DrawLine( RDVertex* pV0, RDVertex* pV1 ) { // If the clip-codes dont exist then compute them. This happens only
// for Transformed vertices that are directly passed in to be rasterized.
if( (pV0->m_qwFVF & D3DFVFP_CLIP) == 0 ) ComputeClipCodesTL( pV0 ); if( (pV1->m_qwFVF & D3DFVFP_CLIP) == 0 ) ComputeClipCodesTL( pV1 );
RDCLIPCODE c0 = pV0->m_clip; RDCLIPCODE c1 = pV1->m_clip;
DWORD dwInter = (c0 & c1); DWORD dwUnion = (c0 | c1); DWORD dwMask = (UseGuardBand()) ? RDCLIPGB_ALL : RDCLIP_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 ) { m_pDev->DrawLine( pV0, pV1 ); return; }
RDCLIPTRIANGLE newline; RDClipVertex cv[2];
MakeClipVertexFromVertex( cv[0], *pV0, dwMask ); MakeClipVertexFromVertex( cv[1], *pV1, dwMask );
newline.v[0] = &cv[0]; newline.v[1] = &cv[1];
if( ClipSingleLine( &newline ) ) { // Temporary Byte Array
if( FAILED(ClipBuf.Grow( 2 )) ) return; MakeVertexFromClipVertex( ClipBuf[0], *(newline.v[0]) ); MakeVertexFromClipVertex( ClipBuf[1], *(newline.v[1]) ); ClipBuf[0].SetFVF( pV0->m_qwFVF ); ClipBuf[1].SetFVF( pV0->m_qwFVF );
m_pDev->DrawLine( &ClipBuf[0], &ClipBuf[1] ); } }
void RefClipper::DrawPoint( RDVertex* pV0 ) { // If the clip-codes dont exist then compute them. This happens only
// for Transformed vertices that are directly passed in to be rasterized.
if( (pV0->m_qwFVF & D3DFVFP_CLIP) == 0 ) ComputeClipCodesTL( pV0 );
RDCLIPCODE c0 = pV0->m_clip; DWORD dwMask = (UseGuardBand()) ? RDCLIPGB_ALL : RDCLIP_ALL;
// if definitely out
#if 0
if( c0 & (RDCLIP_FRONT | RDCLIP_BACK | (1<<RDCLIPGB_LEFTBIT) | (1<<RDCLIPGB_RIGHTBIT) | (1<<RDCLIPGB_TOPBIT) | (1<<RDCLIPGB_BOTTOMBIT)) ) return; #else
if( c0 & dwMask ) return; #endif
// is completely in, just draw it
m_pDev->DrawPoint( pV0 ); }
////////////////////////////////////////////////////////////////////////////
//
// Returns 0, if triangle is clipped. Number of vertices otherwise.
//
// Original vertices should not be modified inside the function
////////////////////////////////////////////////////////////////////////////
int RefClipper::ClipSingleTriangle( RDCLIPTRIANGLE *tri, RDClipVertex ***clipVertexPointer ) { int accept; int i, j; int count; RDClipVertex **inv; RDClipVertex **outv; RDClipVertex *p; ULONG_PTR swapv; RDCOLOR4 diffuse1; // Original colors
RDCOLOR4 specular1; RDCOLOR4 diffuse2; RDCOLOR4 specular2; DWORD dwClipBit; DWORD dwClippedBit;
if( m_dwFlags & RCLIP_DO_FLATSHADING ) { // It is easier to set all vertices to the same color here
RDCOLOR4 diffuse = tri->v[0]->m_diffuse; RDCOLOR4 specular = tri->v[0]->m_specular;
//Save original colors
diffuse1 = tri->v[1]->m_diffuse; specular1 = tri->v[1]->m_specular; diffuse2 = tri->v[2]->m_diffuse; specular2 = tri->v[2]->m_specular;
tri->v[1]->m_diffuse = diffuse; tri->v[1]->m_specular = specular; tri->v[2]->m_diffuse = diffuse; tri->v[2]->m_specular = specular; } accept = (tri->v[0]->m_clip | tri->v[1]->m_clip | tri->v[2]->m_clip);
inv = tri->v; count = 3; outv = clip_vbuf1; clip_color = tri->v[0]->m_diffuse; clip_specular = tri->v[0]->m_specular;
/*
* XXX assumes sizeof(void*) == sizeof(unsigned long) */ { ULONG_PTR tmp1; ULONG_PTR tmp2;
tmp1 = (ULONG_PTR)clip_vbuf1; tmp2 = (ULONG_PTR)clip_vbuf2;
swapv = tmp1 + tmp2; } clip_vertices_used = 0;
#define SWAP(inv, outv) \
inv = outv; \ outv = (RDClipVertex**) (swapv - (ULONG_PTR) outv)
if( accept & RDCLIP_FRONT ) { count = ClipFront( inv, outv, count ); if( count < 3 ) goto out_of_here; SWAP(inv, outv); } if( UseGuardBand() ) { // 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 & RDCLIP_FRONT ) { accept = 0; for (i = 0; i < count; i++) { RDClipVertex *p; p = inv[i]; if( p->m_clip & CLIPPED_FRONT ) accept |= ComputeClipCodeGB( p ); else accept |= p->m_clip; } } if( accept & RDCLIP_BACK ) { count = ClipBack( inv, outv, count ); if( count < 3 ) goto out_of_here; SWAP(inv, outv); } if( accept & RDCLIPGB_LEFT ) { count = ClipLeftGB( inv, outv, count ); if( count < 3 ) goto out_of_here; SWAP(inv, outv); } if( accept & RDCLIPGB_RIGHT ) { count = ClipRightGB( inv, outv, count ); if( count < 3 ) goto out_of_here; SWAP(inv, outv); } if( accept & RDCLIPGB_BOTTOM ) { count = ClipBottomGB( inv, outv, count ); if( count < 3 ) goto out_of_here; SWAP(inv, outv); } if( accept & RDCLIPGB_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 & RDCLIP_FRONT ) { accept = 0; for (i = 0; i < count; i++) { RDClipVertex *p; p = inv[i]; if( p->m_clip & (CLIPPED_FRONT) ) accept |= ComputeClipCode( p ); else accept |= p->m_clip; } } if( accept & RDCLIP_BACK ) { count = ClipBack( inv, outv, count ); if( count < 3 ) goto out_of_here; SWAP(inv, outv); } if( accept & RDCLIP_LEFT ) { count = ClipLeft( inv, outv, count ); if( count < 3 ) goto out_of_here; SWAP(inv, outv); } if( accept & RDCLIP_RIGHT ) { count = ClipRight( inv, outv, count ); if( count < 3 ) goto out_of_here; SWAP(inv, outv); } if( accept & RDCLIP_BOTTOM ) { count = ClipBottom( inv, outv, count ); if( count < 3 ) goto out_of_here; SWAP(inv, outv); } if( accept & RDCLIP_TOP ) { count = ClipTop( inv, outv, count ); if( count < 3 ) goto out_of_here; SWAP(inv, outv); } }
dwClipBit = RDCLIP_USERCLIPPLANE0; dwClippedBit = CLIPPED_USERCLIPPLANE0; // User Clip Planes
for( j=0; j<RD_MAX_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( inv, count );
*clipVertexPointer = inv; current_vbuf = inv; return count;
out_of_here:
*clipVertexPointer = NULL; return 0; }
//-----------------------------------------------------------------------
//
int RefClipper::ClipSingleLine( RDCLIPTRIANGLE *line ) { int accept; int j; D3DVALUE in1, in2; DWORD dwClipBit; DWORD dwClippedBit;
accept = (line->v[0]->m_clip | line->v[1]->m_clip);
clip_color = line->v[0]->m_diffuse; clip_specular = line->v[0]->m_specular;
if( accept & D3DCS_FRONT ) if( ClipLineFront(line) ) goto out_of_here; if( UseGuardBand() ) { // 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 & D3DCS_FRONT ) { RDClipVertex * p; accept = 0; p = line->v[0]; if( p->m_clip & CLIPPED_FRONT ) accept |= ComputeClipCodeGB( p ); else accept |= p->m_clip; p = line->v[1]; if( p->m_clip & CLIPPED_FRONT ) accept |= ComputeClipCodeGB( p ); else accept |= p->m_clip; } if( accept & D3DCS_BACK ) if( ClipLineBack( line ) ) goto out_of_here; if( accept & RDCLIPGB_LEFT ) if( ClipLineLeftGB( line ) ) goto out_of_here; if( accept & RDCLIPGB_RIGHT ) if( ClipLineRightGB( line ) ) goto out_of_here; if( accept & RDCLIPGB_TOP ) if( ClipLineTopGB( line ) ) goto out_of_here; if( accept & RDCLIPGB_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 & D3DCS_FRONT ) { RDClipVertex * p; accept = 0; p = line->v[0]; if( p->m_clip & CLIPPED_FRONT ) accept |= ComputeClipCode( p ); else accept |= p->m_clip; p = line->v[1]; if( p->m_clip & CLIPPED_FRONT ) accept |= ComputeClipCode( p ); else accept |= p->m_clip; } if( accept & D3DCS_BACK ) if( ClipLineBack( line ) ) goto out_of_here; if( accept & D3DCS_LEFT ) if( ClipLineLeft( line ) ) goto out_of_here; if( accept & D3DCS_RIGHT ) if( ClipLineRight( line ) ) goto out_of_here; if( accept & D3DCS_TOP ) if( ClipLineTop( line ) ) goto out_of_here; if( accept & D3DCS_BOTTOM ) if( ClipLineBottom( line ) ) goto out_of_here; }
// User Clip Planes
dwClipBit = RDCLIP_USERCLIPPLANE0; dwClippedBit = CLIPPED_USERCLIPPLANE0; for( j=0; j<RD_MAX_USER_CLIPPLANES; j++) { if( accept & dwClipBit ) { if( ClipLineByPlane( line, &m_xfmUserClipPlanes[j].plane, dwClippedBit )) goto out_of_here; } dwClipBit <<= 1; dwClippedBit <<= 1; }
ComputeScreenCoordinates( line->v, 2 );
return 1; out_of_here: return 0; }
|