|
|
/*==========================================================================;
* * Copyright (C) 1997 Microsoft Corporation. All Rights Reserved. * * File: clip.h * Content: Template for functions to clip primitives * * The following symbol should be defined before included this file: * __PROCESS_LINE_NAME - name for a function to clip triangles * __INDEX_PRIM - name for a function to clip lines * * All these symbols are undefined at the end of this file ***************************************************************************/ #ifdef __INDEX_PRIM
#define __DRAW DRAW_INDEX_PRIM
#else
#define __DRAW DRAW_PRIM
#endif
//*********************************************************************
HRESULT __PROCESS_TRI_LIST_NAME(D3DFE_PROCESSVERTICES *pv) { int vertexSize3; DWORD clipMaskOffScreen; D3DFE_CLIPCODE *clipCode; DWORD i; int interpolate; HRESULT ret; BYTE *vertex; #ifdef __INDEX_PRIM
LPWORD startVertex = pv->lpwIndices; LPWORD index = pv->lpwIndices; DWORD triangleSize; // 3 for DrawPrimitives,
// 4 for ExecuteBuffers (include wFlags)
if (pv->dwFlags & D3DPV_INSIDEEXECUTE) triangleSize = 4; else triangleSize = 3; #else
BYTE *startVertex = (BYTE*)pv->lpvOut; #endif
int primitiveCount; DWORD vertexSize; ClipVertex cv[3]; BOOL vertexTransformed; vertexTransformed = pv->dwFlags & D3DPV_TLVCLIP; clipCode = pv->lpClipFlags; interpolate = SetInterpolationFlags(pv); vertex = (BYTE*)pv->lpvOut; vertexSize = pv->dwOutputSize; primitiveCount = 0; if (pv->dwDeviceFlags & D3DDEV_GUARDBAND) { clipMaskOffScreen = ~__D3DCLIP_INGUARDBAND; } else { clipMaskOffScreen = 0xFFFFFFFF; }
vertexSize3 = vertexSize*3; for (i = pv->dwNumPrimitives; i; i--) { DWORD f1, f2, f3; // vertex clip flags
#ifdef __INDEX_PRIM
DWORD v1, v2, v3; v1 = index[0]; v2 = index[1]; v3 = index[2]; f1 = clipCode[v1]; f2 = clipCode[v2]; f3 = clipCode[v3]; // PSGP implementation should not implement INSIDEEXECUTE
if (pv->dwFlags & D3DPV_INSIDEEXECUTE) // Offset to the current triangle in the execute buffer
((LPDIRECT3DDEVICEI)pv)->dwClipIns_offset = (DWORD)((BYTE*)index - (BYTE*)((LPDIRECT3DDEVICEI)pv)->lpbClipIns_base); #else
f1 = clipCode[0]; f2 = clipCode[1]; f3 = clipCode[2]; #endif
BOOL needClip = FALSE; BOOL offFrustum = FALSE; if (f1 & f2 & f3) offFrustum = TRUE; else if ((f1 | f2 | f3) & clipMaskOffScreen) needClip = TRUE;
if (offFrustum || needClip) {// This tri does need clipping
if (primitiveCount) { // first draw the ones that didn't need clipping
DWORD vertexCount = primitiveCount*3; ret = __DRAW(pv, D3DPT_TRIANGLELIST, startVertex, vertexCount, primitiveCount); if (ret) return ret; #ifndef __INDEX_PRIM
pv->dwVertexBase += vertexCount; #endif
} // reset count and start ptr
primitiveCount = 0; #ifdef __INDEX_PRIM
startVertex = index + triangleSize; #else
pv->dwVertexBase += 3; D3D_INFO(7, "VertexBase:%08lx", pv->dwVertexBase); startVertex = vertex + vertexSize3; #endif
// now deal with the single clipped triangle
// first check if it should just be tossed or if it should be clipped
if (!offFrustum) { BYTE *p1; BYTE *p2; BYTE *p3; #ifdef __INDEX_PRIM
p1 = vertex + v1*vertexSize; p2 = vertex + v2*vertexSize; p3 = vertex + v3*vertexSize; #else
p1 = vertex; p2 = vertex + vertexSize; p3 = p2 + vertexSize; #endif
MAKE_CLIP_VERTEX_FVF(pv, cv[0], p1, f1, vertexTransformed, clipMaskOffScreen); MAKE_CLIP_VERTEX_FVF(pv, cv[1], p2, f2, vertexTransformed, clipMaskOffScreen); MAKE_CLIP_VERTEX_FVF(pv, cv[2], p3, f3, vertexTransformed, clipMaskOffScreen);
#ifdef __INDEX_PRIM
if (pv->dwFlags & D3DPV_INSIDEEXECUTE) // Pass triangle flags for execute buffers
ret = Clip(pv, interpolate, cv, index[3]); else #endif
ret = Clip(pv, interpolate, cv); if (ret) return ret; } } else primitiveCount++; #ifdef __INDEX_PRIM
index += triangleSize; #else
clipCode += 3; vertex += vertexSize3; #endif
} // draw final batch, if any
if (primitiveCount) { ret = __DRAW(pv, D3DPT_TRIANGLELIST, startVertex, primitiveCount*3, primitiveCount); if (ret) return ret; } return D3D_OK; } //------------------------------------------------------------------------------
HRESULT __PROCESS_TRI_STRIP_NAME(D3DFE_PROCESSVERTICES *pv) { DWORD lastIndex; DWORD clipMaskOffScreen; D3DFE_CLIPCODE *clipCode; DWORD i; int interpolate; HRESULT ret; BYTE *vertex; #ifdef __INDEX_PRIM
LPWORD startVertex = pv->lpwIndices; LPWORD index = pv->lpwIndices; #else
BYTE *startVertex = (BYTE*)pv->lpvOut; #endif
int primitiveCount; DWORD vertexSize; ClipVertex cv[3]; BOOL vertexTransformed; vertexTransformed = pv->dwFlags & D3DPV_TLVCLIP; clipCode = pv->lpClipFlags; interpolate = SetInterpolationFlags(pv); vertex = (BYTE*)pv->lpvOut; vertexSize = pv->dwOutputSize; primitiveCount = 0; if (pv->dwDeviceFlags & D3DDEV_GUARDBAND) { clipMaskOffScreen = ~__D3DCLIP_INGUARDBAND; } else { clipMaskOffScreen = 0xFFFFFFFF; }
lastIndex = pv->dwNumPrimitives; for (i=0; i < lastIndex; i++) { DWORD f1, f2, f3; // vertex clip flags
#ifdef __INDEX_PRIM
DWORD v1, v2, v3; v1 = index[0]; v2 = index[1]; v3 = index[2]; f1 = clipCode[v1]; f2 = clipCode[v2]; f3 = clipCode[v3]; #else
f1 = clipCode[0]; f2 = clipCode[1]; f3 = clipCode[2]; #endif
BOOL needClip = FALSE; BOOL offFrustum = FALSE; if (f1 & f2 & f3) offFrustum = TRUE; else if ((f1 | f2 | f3) & clipMaskOffScreen) needClip = TRUE;
if (offFrustum || needClip) { // if this tri does need clipping
if (primitiveCount) { // first draw the ones that didn't need clipping
ret = __DRAW(pv, D3DPT_TRIANGLESTRIP, startVertex, primitiveCount+2, primitiveCount); if (ret) return ret; #ifndef __INDEX_PRIM
pv->dwVertexBase += primitiveCount; #endif
} // reset count and start ptr
primitiveCount = 0; #ifdef __INDEX_PRIM
startVertex = &index[1]; #else
pv->dwVertexBase++; D3D_INFO(7, "VertexBase:%08lx", pv->dwVertexBase); startVertex = vertex + vertexSize; #endif
// now deal with the single clipped triangle
// first check if it should just be tossed or if it should be clipped
if (!offFrustum) { BYTE *p1; BYTE *p2; BYTE *p3; #ifdef __INDEX_PRIM
if (i & 1) { // For odd triangles we have to change orientation
// First vertex should remain the first, because it defines
// the color in FLAT shade mode
DWORD tmp = f2; f2 = f3; f3 = tmp; p1 = vertex + v1*vertexSize; p2 = vertex + v3*vertexSize; p3 = vertex + v2*vertexSize; } else { p1 = vertex + v1*vertexSize; p2 = vertex + v2*vertexSize; p3 = vertex + v3*vertexSize; }
#else
p1 = vertex; if (i & 1) { // For odd triangles we have to change orientation
DWORD tmp = f2; f2 = f3; f3 = tmp; p3 = vertex + vertexSize; p2 = p3 + vertexSize; } else { p2 = vertex + vertexSize; p3 = p2 + vertexSize; } #endif
MAKE_CLIP_VERTEX_FVF(pv, cv[0], p1, f1, vertexTransformed, clipMaskOffScreen); MAKE_CLIP_VERTEX_FVF(pv, cv[1], p2, f2, vertexTransformed, clipMaskOffScreen); MAKE_CLIP_VERTEX_FVF(pv, cv[2], p3, f3, vertexTransformed, clipMaskOffScreen);
ret = Clip(pv, interpolate, cv); if (ret) return ret; } } else { if (primitiveCount == 0 && i & 1) { // Triangle strip can not start from an odd triangle
// Because we use triangle fan, first vertex in the strip
// should be the second in the fan.
// This vertex defines the color in FLAT shading case.
BYTE tmp[__MAX_VERTEX_SIZE*3]; BYTE *p = tmp; #ifdef __INDEX_PRIM
BYTE *saveVer = (BYTE*)pv->lpvOut; DWORD numVer = pv->dwNumVertices; memcpy (p, vertex + v2*vertexSize, vertexSize); p += vertexSize; memcpy (p, vertex + v1*vertexSize, vertexSize); p += vertexSize; memcpy (p, vertex + v3*vertexSize, vertexSize); #else
memcpy(p, vertex + vertexSize, vertexSize); p += vertexSize; memcpy(p, vertex, vertexSize); p += vertexSize; memcpy(p, vertex + vertexSize + vertexSize, vertexSize); #endif
pv->dwFlags |= D3DPV_CLIPPERPRIM | D3DPV_NONCLIPPED; // Mark this call as gen by clipper
ret = DRAW_PRIM(pv, D3DPT_TRIANGLEFAN, tmp, 3, 1); pv->dwFlags &= ~(D3DPV_CLIPPERPRIM | D3DPV_NONCLIPPED); if (ret) return ret; primitiveCount = 0; #ifdef __INDEX_PRIM
startVertex = &index[1]; pv->lpvOut = saveVer; pv->dwNumVertices = numVer; #else
pv->dwVertexBase++; D3D_INFO(7, "VertexBase:%08lx", pv->dwVertexBase); startVertex = vertex + vertexSize; #endif
} else primitiveCount++; } #ifdef __INDEX_PRIM
index++; #else
clipCode++; vertex += vertexSize; #endif
} // draw final batch, if any
if (primitiveCount) { ret = __DRAW(pv, D3DPT_TRIANGLESTRIP, startVertex, primitiveCount+2, primitiveCount); if (ret) return ret; #ifndef __INDEX_PRIM
pv->dwVertexBase += primitiveCount; #endif
} return D3D_OK; } //-----------------------------------------------------------------------------
// The same functions is used for line lists and line strips
//
HRESULT __PROCESS_LINE_NAME(D3DFE_PROCESSVERTICES *pv) { DWORD nextLineOffset; // How many vertices to skip, when going to
// next primitive (1 for strips, 2 for lists)
DWORD countAdd; // Used to compute "real" number of vertices
// from the vertexCount
D3DPRIMITIVETYPE primType; int numPrim = 0; DWORD clipMaskOffScreen; D3DFE_CLIPCODE *clipCode; DWORD i; int interpolate; HRESULT ret; BYTE *vertex; #ifdef __INDEX_PRIM
LPWORD startVertex = pv->lpwIndices; LPWORD index = pv->lpwIndices; #else
BYTE *startVertex = (BYTE*)pv->lpvOut; #endif
int vertexCount; // Primitive count for line strips,
// vertex count for line lists
DWORD vertexSize; ClipVertex cv[3]; BOOL vertexTransformed; vertexTransformed = pv->dwFlags & D3DPV_TLVCLIP; clipCode = pv->lpClipFlags; interpolate = SetInterpolationFlags(pv); vertex = (BYTE*)pv->lpvOut; vertexSize = pv->dwOutputSize; vertexCount = 0; if (pv->dwDeviceFlags & D3DDEV_GUARDBAND) { clipMaskOffScreen = ~__D3DCLIP_INGUARDBAND; } else { clipMaskOffScreen = 0xFFFFFFFF; }
primType = pv->primType; if (primType == D3DPT_LINESTRIP) { nextLineOffset = 1; countAdd = 1; } else { nextLineOffset = 2; countAdd = 0; } for (i = pv->dwNumPrimitives; i; i--) { WORD f1, f2; #ifdef __INDEX_PRIM
WORD v1, v2; v1 = index[0]; v2 = index[1]; f1 = clipCode[v1]; f2 = clipCode[v2]; #else
f1 = clipCode[0]; f2 = clipCode[1]; #endif
BOOL needClip = FALSE; BOOL offFrustum = FALSE; if (f1 & f2) offFrustum = TRUE; else if ((f1 | f2) & clipMaskOffScreen) needClip = TRUE;
if (offFrustum || needClip) { // if this line does need clipping
if (vertexCount) { // first draw the ones that didn't need clipping
ret = __DRAW(pv, primType, startVertex, vertexCount+countAdd, numPrim); if (ret) return ret; #ifndef __INDEX_PRIM
pv->dwVertexBase += vertexCount; #endif
} // reset count and start ptr
vertexCount = 0; numPrim = 0; #ifdef __INDEX_PRIM
startVertex = &index[nextLineOffset]; #else
pv->dwVertexBase += nextLineOffset; D3D_INFO(7, "VertexBase:%08lx", pv->dwVertexBase); startVertex = vertex + nextLineOffset*vertexSize; #endif
// now deal with the single clipped line
// first check if it should just be tossed or if it should be clipped
if (!offFrustum) { #ifdef __INDEX_PRIM
BYTE *p1 = vertex + v1*vertexSize; BYTE *p2 = vertex + v2*vertexSize; #else
BYTE *p1 = vertex; BYTE *p2 = vertex + vertexSize; #endif
ClipTriangle newline;
MAKE_CLIP_VERTEX_FVF(pv, cv[0], p1, f1, vertexTransformed, clipMaskOffScreen); MAKE_CLIP_VERTEX_FVF(pv, cv[1], p2, f2, vertexTransformed, clipMaskOffScreen);
newline.v[0] = &cv[0]; newline.v[1] = &cv[1];
if (ClipSingleLine(pv, &newline, &pv->rExtents, interpolate)) { BYTE *pTLV = (BYTE*)pv->ClipperState.clipBuf.GetAddress(); BYTE *p = pTLV; #ifdef __INDEX_PRIM
BYTE *saveVer = (BYTE*)pv->lpvOut; DWORD numVer = pv->dwNumVertices; #endif
MAKE_TL_VERTEX_FVF(pv, p, newline.v[0]); p += vertexSize; MAKE_TL_VERTEX_FVF(pv, p, newline.v[1]); pv->dwFlags |= D3DPV_CLIPPERPRIM; // Mark this call as gen by clipper
ret = DRAW_PRIM(pv, D3DPT_LINELIST, pTLV, 2, 1); pv->dwFlags &= ~D3DPV_CLIPPERPRIM; if (ret) return ret;
#ifdef __INDEX_PRIM
pv->lpvOut = saveVer; pv->dwNumVertices = numVer; #endif
} } } else { vertexCount += nextLineOffset; numPrim++; } #ifdef __INDEX_PRIM
index += nextLineOffset; #else
vertex += nextLineOffset*vertexSize; clipCode += nextLineOffset; #endif
} // draw final batch, if any
if (vertexCount) { ret = __DRAW(pv, primType, startVertex, vertexCount+countAdd, numPrim); if (ret) return ret; } return D3D_OK; }
#undef __DRAW
#undef __INDEX_PRIM
#undef __PROCESS_LINE_NAME
#undef __PROCESS_TRI_LIST_NAME
#undef __PROCESS_TRI_STRIP_NAME
|