#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> (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; jm_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>= 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& 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& 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& 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<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; jv[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; jv, 2 ); return 1; out_of_here: return 0; }