]> de.git.xonotic.org Git - xonotic/netradiant.git/blobdiff - tools/quake3/q3map2/surface.c
audit all uses of ClipWindingEpsilon and choose the strict variant or not, and explai...
[xonotic/netradiant.git] / tools / quake3 / q3map2 / surface.c
index ba400b082df8068acc0397e7310e03e58233fe8c..e2ec89093b9155fd5946a38e1dc80e2987887e39 100644 (file)
@@ -1356,7 +1356,7 @@ static void SubdivideFace_r( entity_t *e, brush_t *brush, side_t *side, winding_
                if( (subCeil - subFloor) > subdivisions )
                {
                        /* clip the winding */
-                       ClipWindingEpsilon( w, planeNormal, d, epsilon, &frontWinding, &backWinding );
+                       ClipWindingEpsilon( w, planeNormal, d, epsilon, &frontWinding, &backWinding ); /* not strict; we assume we always keep a winding */
 
                        /* the clip may not produce two polygons if it was epsilon close */
                        if( frontWinding == NULL )
@@ -1498,8 +1498,14 @@ void ClipSideIntoTree_r( winding_t *w, side_t *side, node_t *node )
                }
 
                plane = &mapplanes[ node->planenum ];
-               ClipWindingEpsilon ( w, plane->normal, plane->dist,
-                               ON_EPSILON, &front, &back );
+               ClipWindingEpsilonStrict ( w, plane->normal, plane->dist,
+                               ON_EPSILON, &front, &back ); /* strict, we handle the "winding disappeared" case */
+               if(!front && !back)
+               {
+                       /* in doubt, register it in both nodes */
+                       front = CopyWinding(w);
+                       back = CopyWinding(w);
+               }
                FreeWinding( w );
 
                ClipSideIntoTree_r( front, side, node->children[0] );
@@ -2035,6 +2041,13 @@ int FilterWindingIntoTree_r( winding_t *w, mapDrawSurface_t *ds, node_t *node )
                si->mins[ 1 ] != 0.0f || si->maxs[ 1 ] != 0.0f ||
                si->mins[ 2 ] != 0.0f || si->maxs[ 2 ] != 0.0f) )
        {
+               static qboolean warned = qfalse;
+               if(!warned)
+               {
+                       Sys_Printf( "WARNING: this map uses the deformVertexes move hack\n" );
+                       warned = qtrue;
+               }
+
                /* 'fatten' the winding by the shader mins/maxs (parsed from vertexDeform move) */
                /* note this winding is completely invalid (concave, nonplanar, etc) */
                fat = AllocWinding( w->numpoints * 3 + 3 );
@@ -2077,7 +2090,9 @@ int FilterWindingIntoTree_r( winding_t *w, mapDrawSurface_t *ds, node_t *node )
                        VectorCopy( p2->normal, plane2 );
                        plane2[ 3 ] = p2->dist;
                        
-                       #if 1
+                       #if 0
+                               /* div0: this is the plague (inaccurate) */
+
                                /* invert surface plane */
                                VectorSubtract( vec3_origin, plane2, reverse );
                                reverse[ 3 ] = -plane2[ 3 ];
@@ -2088,6 +2103,8 @@ int FilterWindingIntoTree_r( winding_t *w, mapDrawSurface_t *ds, node_t *node )
                                if( DotProduct( plane1, reverse ) > 0.999f && fabs( plane1[ 3 ] - reverse[ 3 ] ) < 0.001f )
                                        return FilterWindingIntoTree_r( w, ds, node->children[ 1 ] );
                        #else
+                               /* div0: this is the cholera (doesn't hit enough) */
+
                                /* the drawsurf might have an associated plane, if so, force a filter here */
                                if( ds->planeNum == node->planenum )
                                        return FilterWindingIntoTree_r( w, ds, node->children[ 0 ] );
@@ -2097,10 +2114,17 @@ int FilterWindingIntoTree_r( winding_t *w, mapDrawSurface_t *ds, node_t *node )
                }
                
                /* clip the winding by this plane */
-               ClipWindingEpsilon( w, plane1, plane1[ 3 ], ON_EPSILON, &front, &back );
+               ClipWindingEpsilonStrict( w, plane1, plane1[ 3 ], ON_EPSILON, &front, &back ); /* strict; we handle the "winding disappeared" case */
                
                /* filter by this plane */
                refs = 0;
+               if( front == NULL && back == NULL )
+               {
+                       /* same plane, this is an ugly hack */
+                       /* but better too many than too few refs */
+                       refs += FilterWindingIntoTree_r( CopyWinding(w), ds, node->children[ 0 ] );
+                       refs += FilterWindingIntoTree_r( CopyWinding(w), ds, node->children[ 1 ] );
+               }
                if( front != NULL )
                        refs += FilterWindingIntoTree_r( front, ds, node->children[ 0 ] );
                if( back != NULL )
@@ -2147,7 +2171,7 @@ subdivides a patch into an approximate curve and filters it into the tree
 
 static int FilterPatchIntoTree( mapDrawSurface_t *ds, tree_t *tree )
 {
-       int                                     x, y, refs;
+       int                                     x, y, refs = 0;
        
        for(y = 0; y + 2 < ds->patchHeight; y += 2)
                for(x = 0; x + 2 < ds->patchWidth; x += 2)