/* Clip a triangle against the viewport and user clip planes. */ static void TAG(clip_draw_triangle)( GLcontext *ctx, TNL_VERTEX *v0, TNL_VERTEX *v1, TNL_VERTEX *v2, GLuint mask ) { LOCAL_VARS; GET_INTERP_FUNC; TNL_VERTEX tmp[MAX_CLIPPED_VERTICES]; TNL_VERTEX *verts = tmp; TNL_VERTEX *(inlist[2][MAX_CLIPPED_VERTICES]); TNL_VERTEX **out; GLuint in = 0; GLuint n = 3; GLuint i; ASSIGN_3V(inlist, v2, v0, v1 ); /* pv rotated to slot zero */ POLY_CLIP( CLIP_RIGHT_BIT, -1, 0, 0, 1 ); POLY_CLIP( CLIP_LEFT_BIT, 1, 0, 0, 1 ); POLY_CLIP( CLIP_TOP_BIT, 0, -1, 0, 1 ); POLY_CLIP( CLIP_BOTTOM_BIT, 0, 1, 0, 1 ); POLY_CLIP( CLIP_FAR_BIT, 0, 0, -1, 1 ); POLY_CLIP( CLIP_NEAR_BIT, 0, 0, 1, 1 ); if ((ctx->_TriangleCaps & DD_FLATSHADE) && v2 != inlist[0]) COPY_PV( ctx, inlist[0], v2 ); out = inlist[in]; DRAW_POLYGON( out, n ); }
static void ClipTriangle(int *indices, int* numIndices) { int mask = 0; mask |= CalcClipMask(Vertices[0]); mask |= CalcClipMask(Vertices[1]); mask |= CalcClipMask(Vertices[2]); if (mask != 0) { for (int i = 0; i < 3; i += 3) { int vlist[2][2*6+1]; int *inlist = vlist[0], *outlist = vlist[1]; int n = 3; int numVertices = 3; inlist[0] = 0; inlist[1] = 1; inlist[2] = 2; // mark this triangle as unused in case it should be completely // clipped indices[0] = SKIP_FLAG; indices[1] = SKIP_FLAG; indices[2] = SKIP_FLAG; POLY_CLIP(CLIP_POS_X_BIT, -1, 0, 0, 1); POLY_CLIP(CLIP_NEG_X_BIT, 1, 0, 0, 1); POLY_CLIP(CLIP_POS_Y_BIT, 0, -1, 0, 1); POLY_CLIP(CLIP_NEG_Y_BIT, 0, 1, 0, 1); POLY_CLIP(CLIP_POS_Z_BIT, 0, 0, 0, 1); POLY_CLIP(CLIP_NEG_Z_BIT, 0, 0, 1, 1); INCSTAT(stats.thisFrame.numTrianglesClipped); // transform the poly in inlist into triangles indices[0] = inlist[0]; indices[1] = inlist[1]; indices[2] = inlist[2]; for (int j = 3; j < n; ++j) { indices[(*numIndices)++] = inlist[0]; indices[(*numIndices)++] = inlist[j - 1]; indices[(*numIndices)++] = inlist[j]; } } } }
void ProcessTriangle(VertexData& v0, VertexData& v1, VertexData& v2, const VertexData &provoking) { if (gstate.isModeThrough()) { // In case of cull reordering, make sure the right color is on the final vertex. if (gstate.getShadeMode() == GE_SHADE_FLAT) { VertexData corrected2 = v2; corrected2.color0 = provoking.color0; corrected2.color1 = provoking.color1; Rasterizer::DrawTriangle(v0, v1, corrected2); } else { Rasterizer::DrawTriangle(v0, v1, v2); } return; } enum { NUM_CLIPPED_VERTICES = 33, NUM_INDICES = NUM_CLIPPED_VERTICES + 3 }; VertexData* Vertices[NUM_INDICES]; VertexData ClippedVertices[NUM_CLIPPED_VERTICES]; for (int i = 0; i < NUM_CLIPPED_VERTICES; ++i) Vertices[i+3] = &ClippedVertices[i]; // TODO: Change logic when it's a backface (why? In what way?) Vertices[0] = &v0; Vertices[1] = &v1; Vertices[2] = &v2; int indices[NUM_INDICES] = { 0, 1, 2, SKIP_FLAG, SKIP_FLAG, SKIP_FLAG, SKIP_FLAG, SKIP_FLAG, SKIP_FLAG, SKIP_FLAG, SKIP_FLAG, SKIP_FLAG, SKIP_FLAG, SKIP_FLAG, SKIP_FLAG, SKIP_FLAG, SKIP_FLAG, SKIP_FLAG, SKIP_FLAG, SKIP_FLAG, SKIP_FLAG }; int numIndices = 3; int mask = 0; mask |= CalcClipMask(v0.clippos); mask |= CalcClipMask(v1.clippos); mask |= CalcClipMask(v2.clippos); if (mask) { for (int i = 0; i < 3; i += 3) { int vlist[2][2*6+1]; int *inlist = vlist[0], *outlist = vlist[1]; int n = 3; int numVertices = 3; inlist[0] = 0; inlist[1] = 1; inlist[2] = 2; // mark this triangle as unused in case it should be completely clipped indices[0] = SKIP_FLAG; indices[1] = SKIP_FLAG; indices[2] = SKIP_FLAG; POLY_CLIP(CLIP_POS_X_BIT, -1, 0, 0, 1); POLY_CLIP(CLIP_NEG_X_BIT, 1, 0, 0, 1); POLY_CLIP(CLIP_POS_Y_BIT, 0, -1, 0, 1); POLY_CLIP(CLIP_NEG_Y_BIT, 0, 1, 0, 1); POLY_CLIP(CLIP_POS_Z_BIT, 0, 0, 0, 1); POLY_CLIP(CLIP_NEG_Z_BIT, 0, 0, 1, 1); // transform the poly in inlist into triangles indices[0] = inlist[0]; indices[1] = inlist[1]; indices[2] = inlist[2]; for (int j = 3; j < n; ++j) { indices[numIndices++] = inlist[0]; indices[numIndices++] = inlist[j - 1]; indices[numIndices++] = inlist[j]; } } } else if (CalcClipMask(v0.clippos) & CalcClipMask(v1.clippos) & CalcClipMask(v2.clippos)) { // If clipping is disabled, only discard the current primitive // if all three vertices lie outside one of the clipping planes return; } for (int i = 0; i + 3 <= numIndices; i += 3) { if (indices[i] != SKIP_FLAG) { VertexData data[3] = { *Vertices[indices[i]], *Vertices[indices[i+1]], *Vertices[indices[i+2]] }; data[0].screenpos = TransformUnit::ClipToScreen(data[0].clippos); data[1].screenpos = TransformUnit::ClipToScreen(data[1].clippos); data[2].screenpos = TransformUnit::ClipToScreen(data[2].clippos); if (gstate.getShadeMode() == GE_SHADE_FLAT) { // So that the order of clipping doesn't matter... data[2].color0 = provoking.color0; data[2].color1 = provoking.color1; } Rasterizer::DrawTriangle(data[0], data[1], data[2]); } } }
void ProcessTriangle(VertexData& v0, VertexData& v1, VertexData& v2) { if (gstate.isModeThrough()) { Rasterizer::DrawTriangle(v0, v1, v2); return; } enum { NUM_CLIPPED_VERTICES = 33, NUM_INDICES = NUM_CLIPPED_VERTICES + 3 }; VertexData* Vertices[NUM_INDICES]; VertexData ClippedVertices[NUM_CLIPPED_VERTICES]; for (int i = 0; i < NUM_CLIPPED_VERTICES; ++i) Vertices[i+3] = &ClippedVertices[i]; // TODO: Change logic when it's a backface Vertices[0] = &v0; Vertices[1] = &v1; Vertices[2] = &v2; int indices[NUM_INDICES] = { 0, 1, 2, SKIP_FLAG, SKIP_FLAG, SKIP_FLAG, SKIP_FLAG, SKIP_FLAG, SKIP_FLAG, SKIP_FLAG, SKIP_FLAG, SKIP_FLAG, SKIP_FLAG, SKIP_FLAG, SKIP_FLAG, SKIP_FLAG, SKIP_FLAG, SKIP_FLAG, SKIP_FLAG, SKIP_FLAG, SKIP_FLAG }; int numIndices = 3; int mask = 0; mask |= CalcClipMask(v0.clippos); mask |= CalcClipMask(v1.clippos); mask |= CalcClipMask(v2.clippos); if (mask && (gstate.clipEnable & 0x1)) { // discard if any vertex is outside the near clipping plane if (mask & CLIP_NEG_Z_BIT) return; for(int i = 0; i < 3; i += 3) { int vlist[2][2*6+1]; int *inlist = vlist[0], *outlist = vlist[1]; int n = 3; int numVertices = 3; inlist[0] = 0; inlist[1] = 1; inlist[2] = 2; // mark this triangle as unused in case it should be completely clipped indices[0] = SKIP_FLAG; indices[1] = SKIP_FLAG; indices[2] = SKIP_FLAG; POLY_CLIP(CLIP_POS_X_BIT, -1, 0, 0, 1); POLY_CLIP(CLIP_NEG_X_BIT, 1, 0, 0, 1); POLY_CLIP(CLIP_POS_Y_BIT, 0, -1, 0, 1); POLY_CLIP(CLIP_NEG_Y_BIT, 0, 1, 0, 1); POLY_CLIP(CLIP_POS_Z_BIT, 0, 0, 0, 1); POLY_CLIP(CLIP_NEG_Z_BIT, 0, 0, 1, 1); // transform the poly in inlist into triangles indices[0] = inlist[0]; indices[1] = inlist[1]; indices[2] = inlist[2]; for (int j = 3; j < n; ++j) { indices[numIndices++] = inlist[0]; indices[numIndices++] = inlist[j - 1]; indices[numIndices++] = inlist[j]; } } } else if (CalcClipMask(v0.clippos) & CalcClipMask(v1.clippos) & CalcClipMask(v2.clippos)) { // If clipping is disabled, only discard the current primitive // if all three vertices lie outside one of the clipping planes return; } for(int i = 0; i+3 <= numIndices; i+=3) { if(indices[i] != SKIP_FLAG) { VertexData data[3] = { *Vertices[indices[i]], *Vertices[indices[i+1]], *Vertices[indices[i+2]] }; data[0].screenpos = TransformUnit::ClipToScreen(data[0].clippos); data[1].screenpos = TransformUnit::ClipToScreen(data[1].clippos); data[2].screenpos = TransformUnit::ClipToScreen(data[2].clippos); Rasterizer::DrawTriangle(data[0], data[1], data[2]); } } }