Clean up clipping somewhat
- no need to update ClipMask on generated vertices - remove the VB->LastClipped value Line clipping algorithm changed and simplified somewhat. The old one was based on the triangle routine and probably wouldn't have recognized lines that were clipped down to nothing (ie culled, but not by a single plane).
This commit is contained in:
@@ -450,11 +450,6 @@ struct vertex_buffer
|
||||
|
||||
/* Inputs to the vertex program stage */
|
||||
GLvector4f *AttribPtr[_TNL_ATTRIB_MAX]; /* GL_NV_vertex_program */
|
||||
|
||||
GLuint LastClipped;
|
||||
/* Private data from _tnl_render_stage that has no business being
|
||||
* in this struct.
|
||||
*/
|
||||
};
|
||||
|
||||
|
||||
|
||||
+46
-36
@@ -42,16 +42,11 @@ do { \
|
||||
GLuint idx = inlist[i]; \
|
||||
GLfloat dp = CLIP_DOTPROD(idx, A, B, C, D ); \
|
||||
\
|
||||
clipmask[idxPrev] |= PLANE; \
|
||||
if (!IS_NEGATIVE(dpPrev)) { \
|
||||
outlist[outcount++] = idxPrev; \
|
||||
clipmask[idxPrev] &= ~PLANE; \
|
||||
} \
|
||||
\
|
||||
if (DIFFERENT_SIGNS(dp, dpPrev)) { \
|
||||
GLuint newvert = VB->LastClipped++; \
|
||||
VB->ClipMask[newvert] = 0; \
|
||||
outlist[outcount++] = newvert; \
|
||||
if (IS_NEGATIVE(dp)) { \
|
||||
/* Going out of bounds. Avoid division by zero as we \
|
||||
* know dp != dpPrev from DIFFERENT_SIGNS, above. \
|
||||
@@ -66,6 +61,7 @@ do { \
|
||||
INTERP_4F( t, coord[newvert], coord[idxPrev], coord[idx]); \
|
||||
interp( ctx, t, newvert, idxPrev, idx, GL_FALSE ); \
|
||||
} \
|
||||
outlist[outcount++] = newvert++; \
|
||||
} \
|
||||
\
|
||||
idxPrev = idx; \
|
||||
@@ -88,27 +84,24 @@ do { \
|
||||
#define LINE_CLIP(PLANE, A, B, C, D ) \
|
||||
do { \
|
||||
if (mask & PLANE) { \
|
||||
GLfloat dpI = CLIP_DOTPROD( ii, A, B, C, D ); \
|
||||
GLfloat dpJ = CLIP_DOTPROD( jj, A, B, C, D ); \
|
||||
GLfloat dp0 = CLIP_DOTPROD( v0, A, B, C, D ); \
|
||||
GLfloat dp1 = CLIP_DOTPROD( v1, A, B, C, D ); \
|
||||
\
|
||||
if (DIFFERENT_SIGNS(dpI, dpJ)) { \
|
||||
GLuint newvert = VB->LastClipped++; \
|
||||
VB->ClipMask[newvert] = 0; \
|
||||
if (IS_NEGATIVE(dpJ)) { \
|
||||
GLfloat t = dpI / (dpI - dpJ); \
|
||||
VB->ClipMask[jj] |= PLANE; \
|
||||
INTERP_4F( t, coord[newvert], coord[ii], coord[jj] ); \
|
||||
interp( ctx, t, newvert, ii, jj, GL_FALSE ); \
|
||||
jj = newvert; \
|
||||
} else { \
|
||||
GLfloat t = dpJ / (dpJ - dpI); \
|
||||
VB->ClipMask[ii] |= PLANE; \
|
||||
INTERP_4F( t, coord[newvert], coord[jj], coord[ii] ); \
|
||||
interp( ctx, t, newvert, jj, ii, GL_FALSE ); \
|
||||
ii = newvert; \
|
||||
} \
|
||||
/* For regular clipping, we know from the clipmask that one of \
|
||||
* these must be negative (otherwise we wouldn't be here). For \
|
||||
* userclip, there is only a single bit for all active planes, \
|
||||
* so we can end up here when there is nothing to do, hence the \
|
||||
* second IS_NEGATIVE() test: \
|
||||
*/ \
|
||||
if (IS_NEGATIVE(dp1)) { \
|
||||
GLfloat t = dp1 / (dp1 - dp0); \
|
||||
if (t > t1) t1 = t; \
|
||||
} else if (IS_NEGATIVE(dp0)) { \
|
||||
GLfloat t = dp0 / (dp0 - dp1); \
|
||||
if (t > t0) t0 = t; \
|
||||
} \
|
||||
else if (IS_NEGATIVE(dpI)) \
|
||||
\
|
||||
if (t0 + t1 >= 1.0) \
|
||||
return; \
|
||||
} \
|
||||
} while (0)
|
||||
@@ -118,15 +111,17 @@ do { \
|
||||
/* Clip a line against the viewport and user clip planes.
|
||||
*/
|
||||
static INLINE void
|
||||
TAG(clip_line)( GLcontext *ctx, GLuint i, GLuint j, GLubyte mask )
|
||||
TAG(clip_line)( GLcontext *ctx, GLuint v0, GLuint v1, GLubyte mask )
|
||||
{
|
||||
TNLcontext *tnl = TNL_CONTEXT(ctx);
|
||||
struct vertex_buffer *VB = &tnl->vb;
|
||||
tnl_interp_func interp = tnl->Driver.Render.Interp;
|
||||
GLfloat (*coord)[4] = VB->ClipPtr->data;
|
||||
GLuint ii = i, jj = j, p;
|
||||
GLuint newvert = VB->Count;
|
||||
GLfloat t0 = 0;
|
||||
GLfloat t1 = 0;
|
||||
GLuint p;
|
||||
|
||||
VB->LastClipped = VB->Count;
|
||||
|
||||
if (mask & 0x3f) {
|
||||
LINE_CLIP( CLIP_RIGHT_BIT, -1, 0, 0, 1 );
|
||||
@@ -149,10 +144,29 @@ TAG(clip_line)( GLcontext *ctx, GLuint i, GLuint j, GLubyte mask )
|
||||
}
|
||||
}
|
||||
|
||||
if ((ctx->_TriangleCaps & DD_FLATSHADE) && j != jj)
|
||||
tnl->Driver.Render.CopyPV( ctx, jj, j );
|
||||
if (VB->ClipMask[v0]) {
|
||||
INTERP_4F( t0, coord[newvert], coord[v0], coord[v1] );
|
||||
interp( ctx, t0, newvert, v0, v1, GL_FALSE );
|
||||
v0 = newvert;
|
||||
newvert++;
|
||||
}
|
||||
else
|
||||
ASSERT(t0 == 0.0);
|
||||
|
||||
tnl->Driver.Render.ClippedLine( ctx, ii, jj );
|
||||
if (VB->ClipMask[v1]) {
|
||||
INTERP_4F( t1, coord[newvert], coord[v1], coord[v0] );
|
||||
interp( ctx, t1, newvert, v1, v0, GL_FALSE );
|
||||
|
||||
if (ctx->_TriangleCaps & DD_FLATSHADE)
|
||||
tnl->Driver.Render.CopyPV( ctx, newvert, v1 );
|
||||
|
||||
v1 = newvert;
|
||||
newvert++;
|
||||
}
|
||||
else
|
||||
ASSERT(t1 == 0.0);
|
||||
|
||||
tnl->Driver.Render.ClippedLine( ctx, v0, v1 );
|
||||
}
|
||||
|
||||
|
||||
@@ -164,18 +178,16 @@ TAG(clip_tri)( GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2, GLubyte mask )
|
||||
TNLcontext *tnl = TNL_CONTEXT(ctx);
|
||||
struct vertex_buffer *VB = &tnl->vb;
|
||||
tnl_interp_func interp = tnl->Driver.Render.Interp;
|
||||
GLuint newvert = VB->Count;
|
||||
GLfloat (*coord)[4] = VB->ClipPtr->data;
|
||||
GLuint pv = v2;
|
||||
GLuint vlist[2][MAX_CLIPPED_VERTICES];
|
||||
GLuint *inlist = vlist[0], *outlist = vlist[1];
|
||||
GLuint p;
|
||||
GLubyte *clipmask = VB->ClipMask;
|
||||
GLuint n = 3;
|
||||
|
||||
ASSIGN_3V(inlist, v2, v0, v1 ); /* pv rotated to slot zero */
|
||||
|
||||
VB->LastClipped = VB->Count;
|
||||
|
||||
if (mask & 0x3f) {
|
||||
POLY_CLIP( CLIP_RIGHT_BIT, -1, 0, 0, 1 );
|
||||
POLY_CLIP( CLIP_LEFT_BIT, 1, 0, 0, 1 );
|
||||
@@ -217,18 +229,16 @@ TAG(clip_quad)( GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2, GLuint v3,
|
||||
TNLcontext *tnl = TNL_CONTEXT(ctx);
|
||||
struct vertex_buffer *VB = &tnl->vb;
|
||||
tnl_interp_func interp = tnl->Driver.Render.Interp;
|
||||
GLuint newvert = VB->Count;
|
||||
GLfloat (*coord)[4] = VB->ClipPtr->data;
|
||||
GLuint pv = v3;
|
||||
GLuint vlist[2][MAX_CLIPPED_VERTICES];
|
||||
GLuint *inlist = vlist[0], *outlist = vlist[1];
|
||||
GLuint p;
|
||||
GLubyte *clipmask = VB->ClipMask;
|
||||
GLuint n = 4;
|
||||
|
||||
ASSIGN_4V(inlist, v3, v0, v1, v2 ); /* pv rotated to slot zero */
|
||||
|
||||
VB->LastClipped = VB->Count;
|
||||
|
||||
if (mask & 0x3f) {
|
||||
POLY_CLIP( CLIP_RIGHT_BIT, -1, 0, 0, 1 );
|
||||
POLY_CLIP( CLIP_LEFT_BIT, 1, 0, 0, 1 );
|
||||
|
||||
Reference in New Issue
Block a user