Importing regression tests for q3map2 from Rambetter-math-fix-experiments into

trunk.  Branch Rambetter-math-fix-experiments can be deleted now.


git-svn-id: svn://svn.icculus.org/gtkradiant/GtkRadiant/trunk@417 8a3a26a2-13c4-0310-b231-cf6edde360e5
This commit is contained in:
rambetter 2011-01-10 06:25:33 +00:00
parent a16ee23adf
commit a36b39a62b
29 changed files with 810 additions and 18 deletions

View file

@ -0,0 +1,16 @@
DESCRIPTION OF PROBLEM:
=======================
Because of the coarse nature of SnapNormal(), planes that are 0.25 degrees
away from being axial are "snapped" to be axial. The "normal epsilon"
is a very small value by default, and cannot go much smaller (without
running into limits of floating point numbers). The problem with
SnapNormal() is that we compare the components of the normal that are near
1, instead of comaring the components that are near 0. This leads to a very
coarse and inaccurate SnapNormal().
If you open the example map in Radiant, you can see that the red brick should
touch the middle checkered brick at the edge. However, once this map is
compiled, the edges are a significant distance apart. This is due to the
coarse and inaccurate nature of SnapNormal(). Likewise, the green brick should
be flush with the center tiled brick, but it's not.

View file

@ -0,0 +1,96 @@
// entity 0
{
"classname" "worldspawn"
// brush 0
{
( 544 312 -8 ) ( -584 312 -8 ) ( -584 -488 -8 ) common/caulk 0 0 0 0.500000 0.500000 0 4 0
( -576 -488 0 ) ( -576 312 0 ) ( 552 312 0 ) radiant_regression_tests/tile 0 0 0 0.500000 0.500000 0 0 0
( -584 -512 8 ) ( 544 -512 8 ) ( 544 -512 0 ) common/caulk 0 0 0 0.500000 0.500000 0 4 0
( 512 -488 8 ) ( 512 312 8 ) ( 512 312 0 ) common/caulk 0 0 0 0.500000 0.500000 0 4 0
( 528 512 8 ) ( -600 512 8 ) ( -600 512 0 ) common/caulk 0 0 0 0.500000 0.500000 0 4 0
( -512 312 8 ) ( -512 -488 8 ) ( -512 -488 0 ) common/caulk 0 0 0 0.500000 0.500000 0 4 0
}
// brush 1
{
( 720 512 0 ) ( 512 512 0 ) ( 512 -512 0 ) common/caulk 0 0 0 0.500000 0.500000 0 4 0
( 512 -512 512 ) ( 512 512 512 ) ( 720 512 512 ) common/caulk 0 0 0 0.500000 0.500000 0 4 0
( 512 -512 512 ) ( 720 -512 512 ) ( 720 -512 -8 ) common/caulk 0 0 0 0.500000 0.500000 0 4 0
( 520 -512 520 ) ( 520 512 520 ) ( 520 512 0 ) common/caulk 0 0 0 0.500000 0.500000 0 4 0
( 720 512 512 ) ( 512 512 512 ) ( 512 512 -8 ) common/caulk 0 0 0 0.500000 0.500000 0 4 0
( 512 512 512 ) ( 512 -512 512 ) ( 512 -512 -8 ) radiant_regression_tests/tile 0 0 0 0.500000 0.500000 0 0 0
}
// brush 2
{
( -512 512 0 ) ( -592 512 0 ) ( -592 -512 0 ) common/caulk 0 0 0 0.500000 0.500000 0 4 0
( -592 -512 512 ) ( -592 512 512 ) ( -512 512 512 ) common/caulk 0 0 0 0.500000 0.500000 0 4 0
( -592 -512 512 ) ( -512 -512 512 ) ( -512 -512 -8 ) common/caulk 0 0 0 0.500000 0.500000 0 4 0
( -512 -512 512 ) ( -512 512 512 ) ( -512 512 -8 ) radiant_regression_tests/tile 0 0 0 0.500000 0.500000 0 0 0
( -512 512 512 ) ( -592 512 512 ) ( -592 512 -8 ) common/caulk 0 0 0 0.500000 0.500000 0 4 0
( -520 512 536 ) ( -520 -512 536 ) ( -520 -512 16 ) common/caulk 0 0 0 0.500000 0.500000 0 4 0
}
// brush 3
{
( 512 512 512 ) ( -512 512 512 ) ( -512 -512 512 ) radiant_regression_tests/tile 0 0 0 0.500000 0.500000 0 0 0
( -488 -512 520 ) ( -488 512 520 ) ( 536 512 520 ) common/caulk 0 0 0 0.500000 0.500000 0 4 0
( -512 -512 664 ) ( 512 -512 664 ) ( 512 -512 512 ) common/caulk 0 0 0 0.500000 0.500000 0 4 0
( 512 -512 664 ) ( 512 512 664 ) ( 512 512 512 ) common/caulk 0 0 0 0.500000 0.500000 0 4 0
( 512 512 664 ) ( -512 512 664 ) ( -512 512 512 ) common/caulk 0 0 0 0.500000 0.500000 0 4 0
( -512 512 664 ) ( -512 -512 664 ) ( -512 -512 512 ) common/caulk 0 0 0 0.500000 0.500000 0 4 0
}
// brush 4
{
( 512 608 0 ) ( -512 608 0 ) ( -512 520 0 ) common/caulk 0 0 0 0.500000 0.500000 0 4 0
( -512 520 512 ) ( -512 608 512 ) ( 512 608 512 ) common/caulk 0 0 0 0.500000 0.500000 0 4 0
( -512 512 512 ) ( 512 512 512 ) ( 512 512 0 ) radiant_regression_tests/tile 0 0 0 0.500000 0.500000 0 0 0
( 512 520 512 ) ( 512 608 512 ) ( 512 608 0 ) common/caulk 0 0 0 0.500000 0.500000 0 4 0
( 512 520 520 ) ( -512 520 520 ) ( -512 520 8 ) common/caulk 0 0 0 0.500000 0.500000 0 4 0
( -512 608 512 ) ( -512 520 512 ) ( -512 520 0 ) common/caulk 0 0 0 0.500000 0.500000 0 4 0
}
// brush 5
{
( 512 -512 0 ) ( -512 -512 0 ) ( -512 -600 0 ) common/caulk 0 0 0 0.500000 0.500000 0 4 0
( -512 -600 512 ) ( -512 -512 512 ) ( 512 -512 512 ) common/caulk 0 0 0 0.500000 0.500000 0 4 0
( -512 -520 520 ) ( 512 -520 520 ) ( 512 -520 8 ) common/caulk 0 0 0 0.500000 0.500000 0 4 0
( 512 -600 512 ) ( 512 -512 512 ) ( 512 -512 0 ) common/caulk 0 0 0 0.500000 0.500000 0 4 0
( 512 -512 512 ) ( -512 -512 512 ) ( -512 -512 0 ) radiant_regression_tests/tile 0 0 0 0.500000 0.500000 0 0 0
( -512 -512 512 ) ( -512 -600 512 ) ( -512 -600 0 ) common/caulk 0 0 0 0.500000 0.500000 0 4 0
}
// brush 6
{
( 512 72 64 ) ( -512 72 64 ) ( -512 -448 64 ) radiant_regression_tests/tile 0 0 0 0.500000 0.500000 0 0 0
( -128 448 260 ) ( 192 448 260 ) ( 192 -448 256 ) radiant_regression_tests/tile 0 0 0 0.500000 0.500000 0 0 0
( -512 -448 256 ) ( 512 -448 256 ) ( 512 -448 56 ) radiant_regression_tests/tile 0 0 0 0.500000 0.500000 0 0 0
( 192 -440 256 ) ( 192 80 256 ) ( 192 80 56 ) radiant_regression_tests/tile 0 0 0 0.500000 0.500000 0 0 0
( 192 448 260 ) ( -128 448 260 ) ( -128 448 64 ) radiant_regression_tests/tile 0 0 0 0.500000 0.500000 0 0 0
( -128 56 256 ) ( -128 -464 256 ) ( -128 -464 56 ) radiant_regression_tests/tile 0 0 0 0.500000 0.500000 0 0 0
}
// brush 7
{
( 192 -448 232 ) ( -128 -448 232 ) ( -128 -472 232 ) radiant_regression_tests/green 0 0 0 0.500000 0.500000 0 0 0
( -128 -472 256 ) ( -128 -448 256 ) ( 192 -448 256 ) radiant_regression_tests/green 0 0 0 0.500000 0.500000 0 0 0
( -128 -472 256 ) ( 192 -472 256 ) ( 192 -472 232 ) radiant_regression_tests/green 0 0 0 0.500000 0.500000 0 0 0
( 192 -472 256 ) ( 192 -448 256 ) ( 192 -448 232 ) radiant_regression_tests/green 0 0 0 0.500000 0.500000 0 0 0
( 192 -448 256 ) ( -128 -448 256 ) ( -128 -448 232 ) radiant_regression_tests/green 0 0 0 0.500000 0.500000 0 0 0
( -128 -448 256 ) ( -128 -472 256 ) ( -128 -472 232 ) radiant_regression_tests/green 0 0 0 0.500000 0.500000 0 0 0
}
// brush 8
{
( 192 472 260 ) ( -128 472 260 ) ( -128 448 260 ) radiant_regression_tests/red 0 0 0 0.500000 0.500000 0 0 0
( -128 448 280 ) ( -128 472 280 ) ( 192 472 280 ) radiant_regression_tests/red 0 0 0 0.500000 0.500000 0 0 0
( -128 448 280 ) ( 192 448 280 ) ( 192 448 256 ) radiant_regression_tests/red 0 0 0 0.500000 0.500000 0 0 0
( 192 448 280 ) ( 192 472 280 ) ( 192 472 256 ) radiant_regression_tests/red 0 0 0 0.500000 0.500000 0 0 0
( 192 472 280 ) ( -128 472 280 ) ( -128 472 256 ) radiant_regression_tests/red 0 0 0 0.500000 0.500000 0 0 0
( -128 472 280 ) ( -128 448 280 ) ( -128 448 256 ) radiant_regression_tests/red 0 0 0 0.500000 0.500000 0 0 0
}
}
// entity 1
{
"light" "3000"
"origin" "0 0 384"
"classname" "light"
}
// entity 2
{
"origin" "0 -64 384"
"classname" "info_player_deathmatch"
}

View file

@ -0,0 +1,4 @@
DESCRIPTION OF PROBLEM:
=======================
I'm testing when windings become degenerate.

View file

@ -0,0 +1,78 @@
// entity 0
{
"classname" "worldspawn"
// brush 0
{
( 256 256 -8 ) ( -256 256 -8 ) ( -256 -264 -8 ) common/caulk 0 0 0 0.500000 0.500000 0 4 0
( -256 -264 0 ) ( -256 256 0 ) ( 256 256 0 ) radiant_regression_tests/tile 0 0 0 0.500000 0.500000 0 0 0
( -256 -256 8 ) ( 256 -256 8 ) ( 256 -256 0 ) common/caulk 0 0 0 0.500000 0.500000 0 4 0
( 256 -264 8 ) ( 256 256 8 ) ( 256 256 0 ) common/caulk 0 0 0 0.500000 0.500000 0 4 0
( 256 256 8 ) ( -256 256 8 ) ( -256 256 0 ) common/caulk 0 0 0 0.500000 0.500000 0 4 0
( -256 256 8 ) ( -256 -264 8 ) ( -256 -264 0 ) common/caulk 0 0 0 0.500000 0.500000 0 4 0
}
// brush 1
{
( 296 256 0 ) ( 256 256 0 ) ( 256 -256 0 ) common/caulk 0 0 0 0.500000 0.500000 0 4 0
( 280 -256 512 ) ( 280 256 512 ) ( 320 256 512 ) common/caulk 0 0 0 0.500000 0.500000 0 4 0
( 256 -256 392 ) ( 296 -256 392 ) ( 296 -256 0 ) common/caulk 0 0 0 0.500000 0.500000 0 4 0
( 264 -256 384 ) ( 264 256 384 ) ( 264 256 -8 ) common/caulk 0 0 0 0.500000 0.500000 0 4 0
( 296 256 392 ) ( 256 256 392 ) ( 256 256 0 ) common/caulk 0 0 0 0.500000 0.500000 0 4 0
( 256 256 392 ) ( 256 -256 392 ) ( 256 -256 0 ) radiant_regression_tests/tile 0 0 0 0.500000 0.500000 0 0 0
}
// brush 2
{
( -256 256 0 ) ( -320 256 0 ) ( -320 -256 0 ) common/caulk 0 0 0 0.500000 0.500000 0 4 0
( -320 -256 512 ) ( -320 256 512 ) ( -256 256 512 ) common/caulk 0 0 0 0.500000 0.500000 0 4 0
( -320 -256 504 ) ( -256 -256 504 ) ( -256 -256 0 ) common/caulk 0 0 0 0.500000 0.500000 0 4 0
( -256 -256 504 ) ( -256 256 504 ) ( -256 256 0 ) radiant_regression_tests/tile 0 0 0 0.500000 0.500000 0 0 0
( -256 256 504 ) ( -320 256 504 ) ( -320 256 0 ) common/caulk 0 0 0 0.500000 0.500000 0 4 0
( -264 256 496 ) ( -264 -256 496 ) ( -264 -256 -8 ) common/caulk 0 0 0 0.500000 0.500000 0 4 0
}
// brush 3
{
( 256 256 512 ) ( -256 256 512 ) ( -256 -256 512 ) radiant_regression_tests/tile 0 0 0 0.500000 0.500000 0 0 0
( -224 -256 520 ) ( -224 256 520 ) ( 288 256 520 ) common/caulk 0 0 0 0.500000 0.500000 0 4 0
( -256 -256 584 ) ( 256 -256 584 ) ( 256 -256 512 ) common/caulk 0 0 0 0.500000 0.500000 0 4 0
( 256 -256 584 ) ( 256 256 584 ) ( 256 256 512 ) common/caulk 0 0 0 0.500000 0.500000 0 4 0
( 256 256 584 ) ( -256 256 584 ) ( -256 256 512 ) common/caulk 0 0 0 0.500000 0.500000 0 4 0
( -256 256 584 ) ( -256 -256 584 ) ( -256 -256 512 ) common/caulk 0 0 0 0.500000 0.500000 0 4 0
}
// brush 4
{
( 256 328 0 ) ( -256 328 0 ) ( -256 256 0 ) common/caulk 0 0 0 0.500000 0.500000 0 4 0
( -256 256 512 ) ( -256 328 512 ) ( 256 328 512 ) common/caulk 0 0 0 0.500000 0.500000 0 4 0
( -256 256 512 ) ( 256 256 512 ) ( 256 256 0 ) radiant_regression_tests/tile 0 0 0 0.500000 0.500000 0 0 0
( 256 256 512 ) ( 256 328 512 ) ( 256 328 0 ) common/caulk 0 0 0 0.500000 0.500000 0 4 0
( 256 264 536 ) ( -256 264 536 ) ( -256 264 24 ) common/caulk 0 0 0 0.500000 0.500000 0 4 0
( -256 328 512 ) ( -256 256 512 ) ( -256 256 0 ) common/caulk 0 0 0 0.500000 0.500000 0 4 0
}
// brush 5
{
( 256 -256 0 ) ( -256 -256 0 ) ( -256 -304 0 ) common/caulk 0 0 0 0.500000 0.500000 0 4 0
( -256 -304 512 ) ( -256 -256 512 ) ( 256 -256 512 ) common/caulk 0 0 0 0.500000 0.500000 0 4 0
( -256 -264 520 ) ( 256 -264 520 ) ( 256 -264 8 ) common/caulk 0 0 0 0.500000 0.500000 0 4 0
( 256 -304 512 ) ( 256 -256 512 ) ( 256 -256 0 ) common/caulk 0 0 0 0.500000 0.500000 0 4 0
( 256 -256 512 ) ( -256 -256 512 ) ( -256 -256 0 ) radiant_regression_tests/tile 0 0 0 0.500000 0.500000 0 0 0
( -256 -256 512 ) ( -256 -304 512 ) ( -256 -304 0 ) common/caulk 0 0 0 0.500000 0.500000 0 4 0
}
// brush 6
{
( 64 0 128 ) ( 8 0 128 ) ( 8 -8 128 ) radiant_regression_tests/red 0 0 0 0.500000 0.500000 0 0 0
( 8 -8 464 ) ( 8 0 464 ) ( 64 0 464 ) radiant_regression_tests/red 0 0 0 0.500000 0.500000 0 0 0
( -240 8 464 ) ( -240 0 464 ) ( -240 0 160 ) radiant_regression_tests/red 0 0 0 0.500000 0.500000 0 0 0
( -240 24 128 ) ( 160 8 128 ) ( -240 24 464 ) radiant_regression_tests/green 0 0 0 0.500000 0.500000 0 0 0
( 160 8 128 ) ( -240 0 128 ) ( 160 8 464 ) radiant_regression_tests/green 0 0 0 0.500000 0.500000 0 0 0
( 159 11 128 ) ( 159 0 128 ) ( 159 11 464 ) radiant_regression_tests/red 0 0 0 0.500000 0.500000 0 0 0
}
}
// entity 1
{
"light" "1000"
"origin" "-40 0 32"
"classname" "light"
}
// entity 2
{
"origin" "-40 128 96"
"classname" "info_player_deathmatch"
}

View file

@ -1,18 +1,17 @@
Index: tools/quake3/q3map2/brush.c Index: tools/quake3/q3map2/brush.c
=================================================================== ===================================================================
--- tools/quake3/q3map2/brush.c (revision 371) --- tools/quake3/q3map2/brush.c (revision 391)
+++ tools/quake3/q3map2/brush.c (working copy) +++ tools/quake3/q3map2/brush.c (working copy)
@@ -356,17 +356,29 @@ @@ -421,10 +421,16 @@
winding_t *w;
side_t *side; side_t *side;
plane_t *plane; plane_t *plane;
+
-
+ static int brushord = -1; + static int brushord = -1;
+ brushord++; + brushord++;
+ +
+ Sys_Printf("In CreateBrushWindings() for brush %i\n", brushord); + Sys_Printf("In CreateBrushWindings() for brush %i\n", brushord);
+
-
/* walk the list of brush sides */ /* walk the list of brush sides */
for( i = 0; i < brush->numsides; i++ ) for( i = 0; i < brush->numsides; i++ )
{ {
@ -21,33 +20,46 @@ Index: tools/quake3/q3map2/brush.c
/* get side and plane */ /* get side and plane */
side = &brush->sides[ i ]; side = &brush->sides[ i ];
plane = &mapplanes[ side->planenum ]; plane = &mapplanes[ side->planenum ];
@@ -435,7 +441,13 @@
/* make huge winding */ #else
w = BaseWindingForPlane( plane->normal, plane->dist ); w = BaseWindingForPlane( plane->normal, plane->dist );
#endif
-
+ +
+ Sys_Printf(" Before clipping we have:\n"); + Sys_Printf(" Before clipping we have:\n");
+ int z; + int z;
+ for (z = 0; z < w->numpoints; z++) { + for (z = 0; z < w->numpoints; z++) {
+ Sys_Printf(" (%.8f %.8f %.8f)\n", w->p[z][0], w->p[z][1], w->p[z][2]); + Sys_Printf(" (%.8f %.8f %.8f)\n", w->p[z][0], w->p[z][1], w->p[z][2]);
+ } + }
+
/* walk the list of brush sides */ /* walk the list of brush sides */
for( j = 0; j < brush->numsides && w != NULL; j++ ) for( j = 0; j < brush->numsides && w != NULL; j++ )
@@ -379,6 +391,11 @@ {
continue; @@ -451,7 +463,20 @@
plane = &mapplanes[ brush->sides[ j ].planenum ^ 1 ]; #else
ChopWindingInPlace( &w, plane->normal, plane->dist, 0 ); // CLIP_EPSILON ); ChopWindingInPlace( &w, plane->normal, plane->dist, 0 ); // CLIP_EPSILON );
#endif
-
+ +
+ Sys_Printf(" After clipping w/ side %i we have:\n", j); + Sys_Printf(" After clipping w/ side %i we have:\n", j);
+ for (z = 0; z < w->numpoints; z++) { + if (w)
+ {
+ for (z = 0; z < w->numpoints; z++)
+ {
+ Sys_Printf(" (%.8f %.8f %.8f)\n", w->p[z][0], w->p[z][1], w->p[z][2]); + Sys_Printf(" (%.8f %.8f %.8f)\n", w->p[z][0], w->p[z][1], w->p[z][2]);
+ } + }
+ }
+ else
+ {
+ Sys_Printf(" winding is NULL\n");
+ }
+
/* ydnar: fix broken windings that would generate trifans */ /* ydnar: fix broken windings that would generate trifans */
FixWinding( w ); #if EXPERIMENTAL_HIGH_PRECISION_MATH_Q3MAP2_FIXES
FixWindingAccu(w);
Index: tools/quake3/q3map2/map.c Index: tools/quake3/q3map2/map.c
=================================================================== ===================================================================
--- tools/quake3/q3map2/map.c (revision 371) --- tools/quake3/q3map2/map.c (revision 391)
+++ tools/quake3/q3map2/map.c (working copy) +++ tools/quake3/q3map2/map.c (working copy)
@@ -803,7 +803,11 @@ @@ -803,7 +803,11 @@
char shader[ MAX_QPATH ]; char shader[ MAX_QPATH ];
@ -74,7 +86,7 @@ Index: tools/quake3/q3map2/map.c
if( !GetToken( qtrue ) ) if( !GetToken( qtrue ) )
break; break;
if( !strcmp( token, "}" ) ) if( !strcmp( token, "}" ) )
@@ -917,6 +924,10 @@ @@ -917,7 +924,16 @@
} }
/* find the plane number */ /* find the plane number */
@ -83,5 +95,11 @@ Index: tools/quake3/q3map2/map.c
+ Sys_Printf(" (%f %f %f)\n", planePoints[1][0], planePoints[1][1], planePoints[1][2]); + Sys_Printf(" (%f %f %f)\n", planePoints[1][0], planePoints[1][1], planePoints[1][2]);
+ Sys_Printf(" (%f %f %f)\n", planePoints[2][0], planePoints[2][1], planePoints[2][2]); + Sys_Printf(" (%f %f %f)\n", planePoints[2][0], planePoints[2][1], planePoints[2][2]);
planenum = MapPlaneFromPoints( planePoints ); planenum = MapPlaneFromPoints( planePoints );
+ Sys_Printf(" normal: (%.10f %.10f %.10f)\n",
+ mapplanes[planenum].normal[0],
+ mapplanes[planenum].normal[1],
+ mapplanes[planenum].normal[2]);
+ Sys_Printf(" dist: %.10f\n", mapplanes[planenum].dist);
side->planenum = planenum; side->planenum = planenum;
/* bp: get the texture mapping for this texturedef / plane combination */

View file

@ -0,0 +1,36 @@
Random notes for Rambetter, don't expect to understand this:
============================================================
Brush 0 is the problem.
Side 0 is the problem (under surf tri).
Side 1 is the +y 4-face.
Side 2 is the -x 4-face.
Side 3 is the -y 4-face.
side 4 is the +z tri.
(6144, 16122) -> (6784, 16241)
x "climb" of side 1 is 6784 - 6144 = 640.
y "climb" of side 1 is 16241 - 16122 = 119.
x/y "climb rate" of side 1 is 640 / 119 = 5.378151261.
After clipping side 0 against side 1, we get
************
**** (-262144, -33762.8125) -> (262144, 63722)
************
The slope of that is (262144 + 262144) / (63722 + 33762.8125) = 5.378150571.
(-262144, y) -> (6784, 16241)
So (6784 + 262144) / (16241 - y) = 640 / 119
So y = 16241 - ((119 * (6784 + 262144)) / 640) = -33762.8
(6144, 16122) -> (262144, y)
So (262144 - 6144) / (y - 16122) = 640 / 119
So y = 16122 + ((119 * (262144 - 6144)) / 640) = 63722
After clipping side 0 against side 1 should have
************
**** (-262144, -33762.8) -> (262144, 63722)
************

View file

@ -0,0 +1,13 @@
DESCRIPTION OF PROBLEM:
=======================
The 4-sided brush in the middle of the room (brush 0) has a duplicate plane.
The last side (side 4) is a duplicate of the third side (side 2) with the
vertexes re-arranged.
I wanted to make sure that ChopWindingInPlaceAccu() is doing the right thing
by setting a winding to NULL when all its points lie on the plane that the
winding is being chopped with. This seems to be the case. My concern was
that both windings for that duplicate plane will be NULL'ed out.
Seems that some other code might be fixing duplicate planes. That's OK.

View file

@ -0,0 +1,77 @@
// entity 0
{
"classname" "worldspawn"
// brush 0
{
( 136 128 64 ) ( -128 128 64 ) ( -128 -192 64 ) radiant_regression_tests/tile 0 0 0 0.500000 0.500000 0 0 0
( 136 128 384 ) ( -128 128 384 ) ( -128 128 0 ) radiant_regression_tests/tile 0 0 0 0.500000 0.500000 0 0 0
( 128 -192 0 ) ( -128 128 0 ) ( 128 -192 384 ) radiant_regression_tests/tile 0 0 0 0.500000 0.500000 0 0 0
( -128 128 256 ) ( 128 128 64 ) ( -128 -192 256 ) radiant_regression_tests/tile 0 0 0 0.500000 0.500000 0 0 0
( 128 -192 384 ) ( 128 -192 0 ) ( -128 128 0 ) radiant_regression_tests/tile 0 0 0 0.500000 0.500000 0 0 0
}
// brush 1
{
( 256 256 -8 ) ( -256 256 -8 ) ( -256 -256 -8 ) common/caulk 0 0 0 0.500000 0.500000 0 4 0
( -256 -256 0 ) ( -256 256 0 ) ( 256 256 0 ) radiant_regression_tests/tile 0 0 0 0.500000 0.500000 0 0 0
( -256 -256 8 ) ( 256 -256 8 ) ( 256 -256 0 ) common/caulk 0 0 0 0.500000 0.500000 0 4 0
( 256 -256 8 ) ( 256 256 8 ) ( 256 256 0 ) common/caulk 0 0 0 0.500000 0.500000 0 4 0
( 256 256 8 ) ( -256 256 8 ) ( -256 256 0 ) common/caulk 0 0 0 0.500000 0.500000 0 4 0
( -256 256 8 ) ( -256 -256 8 ) ( -256 -256 0 ) common/caulk 0 0 0 0.500000 0.500000 0 4 0
}
// brush 2
{
( -256 256 0 ) ( -280 256 0 ) ( -280 -256 0 ) common/caulk 0 0 0 0.500000 0.500000 0 4 0
( -280 -256 384 ) ( -280 256 384 ) ( -256 256 384 ) common/caulk 0 0 0 0.500000 0.500000 0 4 0
( -280 -256 384 ) ( -256 -256 384 ) ( -256 -256 0 ) common/caulk 0 0 0 0.500000 0.500000 0 4 0
( -256 -256 384 ) ( -256 256 384 ) ( -256 256 0 ) radiant_regression_tests/tile 0 0 0 0.500000 0.500000 0 0 0
( -256 256 384 ) ( -280 256 384 ) ( -280 256 0 ) common/caulk 0 0 0 0.500000 0.500000 0 4 0
( -264 256 392 ) ( -264 -256 392 ) ( -264 -256 8 ) common/caulk 0 0 0 0.500000 0.500000 0 4 0
}
// brush 3
{
( 280 256 0 ) ( 256 256 0 ) ( 256 -256 0 ) common/caulk 0 0 0 0.500000 0.500000 0 4 0
( 256 -256 384 ) ( 256 256 384 ) ( 280 256 384 ) common/caulk 0 0 0 0.500000 0.500000 0 4 0
( 256 -256 384 ) ( 280 -256 384 ) ( 280 -256 0 ) common/caulk 0 0 0 0.500000 0.500000 0 4 0
( 264 -256 384 ) ( 264 256 384 ) ( 264 256 0 ) common/caulk 0 0 0 0.500000 0.500000 0 4 0
( 280 256 384 ) ( 256 256 384 ) ( 256 256 0 ) common/caulk 0 0 0 0.500000 0.500000 0 4 0
( 256 256 384 ) ( 256 -256 384 ) ( 256 -256 0 ) radiant_regression_tests/tile 0 0 0 0.500000 0.500000 0 0 0
}
// brush 4
{
( 256 256 384 ) ( -256 256 384 ) ( -256 -256 384 ) radiant_regression_tests/tile 0 0 0 0.500000 0.500000 0 0 0
( -248 -256 392 ) ( -248 256 392 ) ( 264 256 392 ) common/caulk 0 0 0 0.500000 0.500000 0 4 0
( -256 -256 424 ) ( 256 -256 424 ) ( 256 -256 384 ) common/caulk 0 0 0 0.500000 0.500000 0 4 0
( 256 -256 424 ) ( 256 256 424 ) ( 256 256 384 ) common/caulk 0 0 0 0.500000 0.500000 0 4 0
( 256 256 424 ) ( -256 256 424 ) ( -256 256 384 ) common/caulk 0 0 0 0.500000 0.500000 0 4 0
( -256 256 424 ) ( -256 -256 424 ) ( -256 -256 384 ) common/caulk 0 0 0 0.500000 0.500000 0 4 0
}
// brush 5
{
( 256 296 0 ) ( -256 296 0 ) ( -256 256 0 ) common/caulk 0 0 0 0.500000 0.500000 0 4 0
( -256 256 384 ) ( -256 296 384 ) ( 256 296 384 ) common/caulk 0 0 0 0.500000 0.500000 0 4 0
( -256 256 384 ) ( 256 256 384 ) ( 256 256 0 ) radiant_regression_tests/tile 0 0 0 0.500000 0.500000 0 0 0
( 256 256 384 ) ( 256 296 384 ) ( 256 296 0 ) common/caulk 0 0 0 0.500000 0.500000 0 4 0
( 256 264 392 ) ( -256 264 392 ) ( -256 264 8 ) common/caulk 0 0 0 0.500000 0.500000 0 4 0
( -256 296 384 ) ( -256 256 384 ) ( -256 256 0 ) common/caulk 0 0 0 0.500000 0.500000 0 4 0
}
// brush 6
{
( 256 -256 0 ) ( -256 -256 0 ) ( -256 -296 0 ) common/caulk 0 0 0 0.500000 0.500000 0 4 0
( -256 -296 384 ) ( -256 -256 384 ) ( 256 -256 384 ) common/caulk 0 0 0 0.500000 0.500000 0 4 0
( -256 -264 392 ) ( 256 -264 392 ) ( 256 -264 8 ) common/caulk 0 0 0 0.500000 0.500000 0 4 0
( 256 -296 384 ) ( 256 -256 384 ) ( 256 -256 0 ) common/caulk 0 0 0 0.500000 0.500000 0 4 0
( 256 -256 384 ) ( -256 -256 384 ) ( -256 -256 0 ) radiant_regression_tests/tile 0 0 0 0.500000 0.500000 0 0 0
( -256 -256 384 ) ( -256 -296 384 ) ( -256 -296 0 ) common/caulk 0 0 0 0.500000 0.500000 0 4 0
}
}
// entity 1
{
"origin" "-8 16 256"
"classname" "info_player_deathmatch"
}
// entity 2
{
"light" "1000"
"origin" "-32 -40 256"
"classname" "light"
}

View file

@ -0,0 +1,129 @@
DESCRIPTION OF PROBLEM:
=======================
This example map demonstrates what a relatively large value for plane distance
epsilon can do as far as destroying draw surfaces. The plane distance
epsilon was 0.01 at the time of this writing. This means that two planes
with the same normal and a distance 0.00999 apart are considered to be the
same plane.
The recommended value of plane distance epsilon is more along the lines of
0.001; however, we can't currently change this epsilon to that value due to
lack of resolution in 32 bit floating point integers in the 2^16 number range.
The smallest epsilon in 32 bit float land that can be added to 2^16 that
results in a value greater than 2^16 is approximately 0.007, which is already
practically the current default plane distance epsilon (0.01).
Brush 0 in the example map is a 6-sided brush with red top face. The red top
face is defined such in the .map file:
( -127 256 513 ) ( -127 384 513 ) ( 1 384 512 )
During the -bsp stage,
In ParseRawBrush() for brush 0
Side 4:
(-127.000000 256.000000 513.000000)
(-127.000000 384.000000 513.000000)
(1.000000 384.000000 512.000000)
normal: (0.0078122616 0.0000000000 0.9999694824)
dist: 511.9921875000
Now brush 1, the 4-sided brush with the red top face, has the following
defined as the red top face:
( -128 0 513 ) ( -128 128 513 ) ( 0 128 512 )
It's almost the same plane, only off by a distance of about 0.01.
During compiling:
In ParseRawBrush() for brush 1
Side 1:
(-128.000000 0.000000 513.000000)
(-128.000000 128.000000 513.000000)
(0.000000 128.000000 512.000000)
normal: (0.0078122616 0.0000000000 0.9999694824)
dist: 511.9921875000
Note that the normal and dist are identical to the plane above, even though
the two are different. This leads to multiplying errors later on, when this
side is intersected with the bottom green face. In particular, the blue face
disappears from the map. The blue face:
In CreateBrushWindings() for brush 1
Handling side 2 on the brush
Before clipping we have:
(-262144.00000000 0.00000000 262144.00000000)
(262144.00000000 0.00000000 262144.00000000)
(262144.00000000 -0.00000000 -262144.00000000)
(-262144.00000000 0.00000000 -262144.00000000)
After clipping w/ side 0 we have:
(-262144.00000000 0.00000000 262144.00000000)
(262144.00000000 0.00000000 262144.00000000)
(262144.00000000 0.00000000 -19977.00073172)
(-262144.00000000 0.00000000 20983.00073758)
After clipping w/ side 1 we have:
(262144.00000000 0.00000000 -1535.99218726)
(262144.00000000 0.00000000 -19977.00073172)
(-128.11106773 0.00000000 513.00868046)
After clipping w/ side 3 we have:
(0.00000000 0.00000000 503.00000293)
(-128.11106773 0.00000000 513.00868046)
(-0.00000000 0.00000000 512.00781274)
We see the error is greater than 0.1 in the X value -128.11106773. This
causes the draw surface to be discarded in processing later on. We must
not allow such a great error. An error greater than or equal to 0.1 is
considered to be very bad.
This disappearing blue triangle can be fixed simply by deleting brush 0,
the 6-sided brush that causes the bad plane alias. I would suggest deleting
this brush by editing the .map file manually (and then renumbering the brushes
manually).
After deleting this brush:
In ParseRawBrush() for brush 0
Side 1:
(-128.000000 0.000000 513.000000)
(-128.000000 128.000000 513.000000)
(0.000000 128.000000 512.000000)
normal: (0.0078122616 0.0000000000 0.9999694824)
dist: 511.9843750000
In CreateBrushWindings() for brush 0
Handling side 1 on the brush
Before clipping we have:
(262132.00000000 262136.00000000 -1535.90625143)
(262132.00000000 -262136.00000000 -1535.90625143)
(-262124.00048828 -262136.00000000 2559.84375238)
(-262124.00048828 262136.00000000 2559.84375238)
After clipping w/ side 0 we have:
(262132.00000000 262136.00000000 -1535.90625143)
(262132.00000000 -262136.00000000 -1535.90625143)
(-127.99993289 -262136.00000000 512.99999805)
(-127.99993289 262136.00000000 512.99999805)
After clipping w/ side 2 we have:
(262132.00000000 262136.00000000 -1535.90625143)
(262132.00000000 -0.00000000 -1535.90625143)
(-127.99993289 -0.00000000 512.99999805)
(-127.99993289 262136.00000000 512.99999805)
After clipping w/ side 3 we have:
(0.00000000 0.00000000 511.99999857)
(-127.99993289 -0.00000000 512.99999805)
(-127.99993289 127.99993289 512.99999805)
Note that we're way more accurate now, and we're nowhere near to approaching
the 0.1 error. All it took was the deletion of a seemintly unrelated brush.
SOLUTION TO PROBLEM:
====================
The suggested fix is to increase the resolution of plane distance from 32 bit
float to 64 bit float for the relevant brush processing operations. After that
is done, decrease the default plane distance epsilon from 0.01 to 0.001. Note
that even though plane distance epsilon can be specified on the command-line,
it will do no good (even if set to 0) if the plane distance is close to
2^16.

View file

@ -0,0 +1,85 @@
// entity 0
{
"classname" "worldspawn"
// brush 0
{
( -127 384 513 ) ( -127 256 513 ) ( -127 256 384 ) radiant_regression_tests/tile 0 0 0 0.500000 0.500000 0 0 0
( 1 384 512 ) ( -127 384 512 ) ( -127 384 384 ) radiant_regression_tests/tile 0 0 0 0.500000 0.500000 0 0 0
( 1 256 512 ) ( 1 384 512 ) ( 1 384 384 ) radiant_regression_tests/tile 0 0 0 0.500000 0.500000 0 0 0
( -127 256 512 ) ( 1 256 512 ) ( 1 256 384 ) radiant_regression_tests/tile 0 0 0 0.500000 0.500000 0 0 0
( -127 256 513 ) ( -127 384 513 ) ( 1 384 512 ) radiant_regression_tests/red 0 0 0 0.500000 0.500000 0 0 0
( 1 384 384 ) ( -127 384 384 ) ( -127 256 384 ) radiant_regression_tests/tile 0 0 0 0.500000 0.500000 0 0 0
}
// brush 1
{
( 0 128 503 ) ( -128 128 513 ) ( 0 0 503 ) radiant_regression_tests/green 0 0 0 0.500000 0.500000 0 0 0
( -128 0 513 ) ( -128 128 513 ) ( 0 128 512 ) radiant_regression_tests/red 0 0 0 0.500000 0.500000 0 0 0
( -128 0 512 ) ( 0 0 512 ) ( 0 0 384 ) radiant_regression_tests/blue 0 0 0 0.500000 0.500000 0 0 0
( -128 128 503 ) ( 0 0 503 ) ( -128 128 513 ) radiant_regression_tests/tile 0 0 0 0.500000 0.500000 0 0 0
}
// brush 2
{
( -128 472 8 ) ( -128 320 8 ) ( -128 320 0 ) common/caulk 0 0 0 0.500000 0.500000 0 4 0
( -232 512 8 ) ( -416 512 8 ) ( -416 512 0 ) common/caulk 0 0 0 0.500000 0.500000 0 4 0
( 512 -304 8 ) ( 512 -152 8 ) ( 512 -152 0 ) common/caulk 0 0 0 0.500000 0.500000 0 4 0
( 48 -512 8 ) ( 232 -512 8 ) ( 232 -512 0 ) common/caulk 0 0 0 0.500000 0.500000 0 4 0
( -432 232 0 ) ( -432 384 0 ) ( -248 384 0 ) radiant_regression_tests/tile 0 0 0 0.500000 0.500000 0 0 0
( -256 384 -8 ) ( -440 384 -8 ) ( -440 232 -8 ) common/caulk 0 0 0 0.500000 0.500000 0 4 0
}
// brush 3
{
( -136 512 1040 ) ( -136 -512 1040 ) ( -136 -512 8 ) common/caulk 0 0 0 0.500000 0.500000 0 4 0
( -512 512 1032 ) ( -520 512 1032 ) ( -520 512 0 ) common/caulk 0 0 0 0.500000 0.500000 0 4 0
( -128 -512 1032 ) ( -128 512 1032 ) ( -128 512 0 ) radiant_regression_tests/tile 0 0 0 0.500000 0.500000 0 0 0
( -520 -512 1032 ) ( -512 -512 1032 ) ( -512 -512 0 ) common/caulk 0 0 0 0.500000 0.500000 0 4 0
( -520 -512 1024 ) ( -520 512 1024 ) ( -512 512 1024 ) common/caulk 0 0 0 0.500000 0.500000 0 4 0
( -512 512 0 ) ( -520 512 0 ) ( -520 -512 0 ) common/caulk 0 0 0 0.500000 0.500000 0 4 0
}
// brush 4
{
( 512 512 1024 ) ( 512 -512 1024 ) ( 512 -512 0 ) radiant_regression_tests/tile 0 0 0 0.500000 0.500000 0 0 0
( 592 512 1024 ) ( 512 512 1024 ) ( 512 512 0 ) common/caulk 0 0 0 0.500000 0.500000 0 4 0
( 520 -512 1000 ) ( 520 512 1000 ) ( 520 512 -24 ) common/caulk 0 0 0 0.500000 0.500000 0 4 0
( 512 -512 1024 ) ( 592 -512 1024 ) ( 592 -512 0 ) common/caulk 0 0 0 0.500000 0.500000 0 4 0
( 512 -512 1024 ) ( 512 512 1024 ) ( 592 512 1024 ) common/caulk 0 0 0 0.500000 0.500000 0 4 0
( 592 512 0 ) ( 512 512 0 ) ( 512 -512 0 ) common/caulk 0 0 0 0.500000 0.500000 0 4 0
}
// brush 5
{
( -128 512 1200 ) ( -128 -512 1200 ) ( -128 -512 1024 ) common/caulk 0 0 0 0.500000 0.500000 0 4 0
( 512 512 1200 ) ( -512 512 1200 ) ( -512 512 1024 ) common/caulk 0 0 0 0.500000 0.500000 0 4 0
( 512 -512 1200 ) ( 512 512 1200 ) ( 512 512 1024 ) common/caulk 0 0 0 0.500000 0.500000 0 4 0
( -512 -512 1200 ) ( 512 -512 1200 ) ( 512 -512 1024 ) common/caulk 0 0 0 0.500000 0.500000 0 4 0
( -456 -512 1032 ) ( -456 512 1032 ) ( 568 512 1032 ) common/caulk 0 0 0 0.500000 0.500000 0 4 0
( 512 512 1024 ) ( -512 512 1024 ) ( -512 -512 1024 ) radiant_regression_tests/tile 0 0 0 0.500000 0.500000 0 0 0
}
// brush 6
{
( -128 712 1024 ) ( -128 512 1024 ) ( -128 512 0 ) common/caulk 0 0 0 0.500000 0.500000 0 4 0
( 512 520 1040 ) ( -512 520 1040 ) ( -512 520 16 ) common/caulk 0 0 0 0.500000 0.500000 0 4 0
( 512 512 1024 ) ( 512 712 1024 ) ( 512 712 0 ) common/caulk 0 0 0 0.500000 0.500000 0 4 0
( -512 512 1024 ) ( 512 512 1024 ) ( 512 512 0 ) radiant_regression_tests/tile 0 0 0 0.500000 0.500000 0 0 0
( -512 512 1024 ) ( -512 712 1024 ) ( 512 712 1024 ) common/caulk 0 0 0 0.500000 0.500000 0 4 0
( 512 712 0 ) ( -512 712 0 ) ( -512 512 0 ) common/caulk 0 0 0 0.500000 0.500000 0 4 0
}
// brush 7
{
( -128 -512 1024 ) ( -128 -624 1024 ) ( -128 -624 56 ) common/caulk 0 0 0 0.500000 0.500000 0 4 0
( 512 -512 1024 ) ( -512 -512 1024 ) ( -512 -512 56 ) radiant_regression_tests/tile 0 0 0 0.500000 0.500000 0 0 0
( 512 -624 1024 ) ( 512 -512 1024 ) ( 512 -512 56 ) common/caulk 0 0 0 0.500000 0.500000 0 4 0
( -512 -520 1048 ) ( 512 -520 1048 ) ( 512 -520 80 ) common/caulk 0 0 0 0.500000 0.500000 0 4 0
( -512 -624 1024 ) ( -512 -512 1024 ) ( 512 -512 1024 ) common/caulk 0 0 0 0.500000 0.500000 0 4 0
( 512 -504 0 ) ( -512 -504 0 ) ( -512 -616 0 ) common/caulk 0 0 0 0.500000 0.500000 0 4 0
}
}
// entity 1
{
"classname" "light"
"origin" "192 64 640"
"light" "3000"
}
// entity 2
{
"classname" "info_player_deathmatch"
"origin" "-64 64 640"
}

View file

@ -0,0 +1,27 @@
DESCRIPTION OF PROBLEM:
=======================
The example map, maps/segmentation_fault.map, contains an example of this
bug. q3map2 might segfault while compiling this map. This sort of thing
might happen in certain intermediate versions of q3map2 while work is being
done on fixing the math accuracy. The bug may not have happened in older
version of q3map2, before the math accuracy issues were addressed.
To trigger the bug, compile the map; you don't need -vis or -light. Only
-bsp (the first q3map2 stage) is necessary to trigger the bug. The only
entities in the map are a light and a info_player_deathmatch, so the map will
compile for any Q3 mod.
Here is a description of the problem brush (brush #0):
side 0: -z face
side 1: +z face
side 2: -y face
side 3: +x face
side 4: +y face
side 5: -x face
side 6: problem side "accidentally showed up" :-)
Side 6 is actually a superfluous plane and will be NULL'ed out in the code.
If the code does not handle a NULL'ed out winding correctly, it will
segfault.

View file

@ -0,0 +1,79 @@
// entity 0
{
"classname" "worldspawn"
// brush 0
{
( 10296 17600 -592 ) ( 10240 17600 -592 ) ( 10240 17472 -592 ) radiant_regression_tests/tile 0 0 0 0.500000 0.500000 134217728 257 0
( 10280 17472 -576 ) ( 10280 17600 -576 ) ( 10336 17600 -576 ) radiant_regression_tests/tile 0 0 0 0.500000 0.500000 134217728 257 0
( 10280 17472 -576 ) ( 10336 17472 -576 ) ( 10336 17472 -1600 ) radiant_regression_tests/tile 0 0 0 0.500000 0.500000 134217728 257 0
( 10367 17472 -576 ) ( 10367 17600 -576 ) ( 10367 17600 -1600 ) radiant_regression_tests/tile 0 0 0 0.500000 0.500000 134217728 257 0
( 10328 17727 -576 ) ( 10272 17727 -576 ) ( 10272 17727 -1600 ) radiant_regression_tests/tile 0 0 0 0.500000 0.500000 134217728 257 0
( 10240 17608 -576 ) ( 10240 17480 -576 ) ( 10240 17480 -1600 ) radiant_regression_tests/tile 0 0 0 0.500000 0.500000 134217728 257 0
( 10240 17727 -576 ) ( 10240 17726 -621 ) ( 10335 17727 -576 ) radiant_regression_tests/tile 0 0 0 0.500000 0.500000 134217728 257 0
}
// brush 1
{
( 10504 17800 -768 ) ( 10112 17800 -768 ) ( 10112 17792 -768 ) common/caulk 0 0 0 0.500000 0.500000 0 4 0
( 10112 17792 -320 ) ( 10112 17800 -320 ) ( 10504 17800 -320 ) common/caulk 0 0 0 0.500000 0.500000 0 4 0
( 10112 17792 -576 ) ( 10504 17792 -576 ) ( 10504 17792 -592 ) radiant_regression_tests/tile 0 0 0 0.500000 0.500000 0 0 0
( 10496 17792 -576 ) ( 10496 17800 -576 ) ( 10496 17800 -592 ) common/caulk 0 0 0 0.500000 0.500000 0 4 0
( 10504 17800 -576 ) ( 10112 17800 -576 ) ( 10112 17800 -592 ) common/caulk 0 0 0 0.500000 0.500000 0 4 0
( 10112 17800 -576 ) ( 10112 17792 -576 ) ( 10112 17792 -592 ) common/caulk 0 0 0 0.500000 0.500000 0 4 0
}
// brush 2
{
( 10496 17408 -768 ) ( 10112 17408 -768 ) ( 10112 17392 -768 ) common/caulk 0 0 0 0.500000 0.500000 0 4 0
( 10112 17384 -320 ) ( 10112 17400 -320 ) ( 10496 17400 -320 ) common/caulk 0 0 0 0.500000 0.500000 0 4 0
( 10112 17400 -544 ) ( 10496 17400 -544 ) ( 10496 17400 -768 ) common/caulk 0 0 0 0.500000 0.500000 0 4 0
( 10496 17392 -544 ) ( 10496 17408 -544 ) ( 10496 17408 -768 ) common/caulk 0 0 0 0.500000 0.500000 0 4 0
( 10496 17408 -544 ) ( 10112 17408 -544 ) ( 10112 17408 -768 ) radiant_regression_tests/tile 0 0 0 0.500000 0.500000 0 0 0
( 10112 17408 -544 ) ( 10112 17392 -544 ) ( 10112 17392 -768 ) common/caulk 0 0 0 0.500000 0.500000 0 4 0
}
// brush 3
{
( 10568 17784 -768 ) ( 10496 17784 -768 ) ( 10496 17408 -768 ) common/caulk 0 0 0 0.500000 0.500000 0 4 0
( 10496 17408 -320 ) ( 10496 17784 -320 ) ( 10568 17784 -320 ) common/caulk 0 0 0 0.500000 0.500000 0 4 0
( 10496 17408 -320 ) ( 10568 17408 -320 ) ( 10568 17408 -768 ) common/caulk 0 0 0 0.500000 0.500000 0 4 0
( 10504 17400 -320 ) ( 10504 17776 -320 ) ( 10504 17776 -768 ) common/caulk 0 0 0 0.500000 0.500000 0 4 0
( 10568 17792 -320 ) ( 10496 17792 -320 ) ( 10496 17792 -768 ) common/caulk 0 0 0 0.500000 0.500000 0 4 0
( 10496 17784 -320 ) ( 10496 17408 -320 ) ( 10496 17408 -768 ) radiant_regression_tests/tile 0 0 0 0.500000 0.500000 0 0 0
}
// brush 4
{
( 10112 17792 -768 ) ( 10072 17792 -768 ) ( 10072 17408 -768 ) common/caulk 0 0 0 0.500000 0.500000 0 4 0
( 10072 17408 -320 ) ( 10072 17792 -320 ) ( 10112 17792 -320 ) common/caulk 0 0 0 0.500000 0.500000 0 4 0
( 10072 17408 -320 ) ( 10112 17408 -320 ) ( 10112 17408 -768 ) common/caulk 0 0 0 0.500000 0.500000 0 4 0
( 10112 17408 -320 ) ( 10112 17792 -320 ) ( 10112 17792 -768 ) radiant_regression_tests/tile 0 0 0 0.500000 0.500000 0 0 0
( 10112 17792 -320 ) ( 10072 17792 -320 ) ( 10072 17792 -768 ) common/caulk 0 0 0 0.500000 0.500000 0 4 0
( 10104 17792 -320 ) ( 10104 17408 -320 ) ( 10104 17408 -768 ) common/caulk 0 0 0 0.500000 0.500000 0 4 0
}
// brush 5
{
( 10496 17792 -320 ) ( 10112 17792 -320 ) ( 10112 17408 -320 ) radiant_regression_tests/tile 0 0 0 0.500000 0.500000 0 0 0
( 10112 17408 -312 ) ( 10112 17792 -312 ) ( 10496 17792 -312 ) common/caulk 0 0 0 0.500000 0.500000 0 4 0
( 10112 17408 -232 ) ( 10496 17408 -232 ) ( 10496 17408 -320 ) common/caulk 0 0 0 0.500000 0.500000 0 4 0
( 10496 17408 -232 ) ( 10496 17792 -232 ) ( 10496 17792 -320 ) common/caulk 0 0 0 0.500000 0.500000 0 4 0
( 10496 17792 -232 ) ( 10112 17792 -232 ) ( 10112 17792 -320 ) common/caulk 0 0 0 0.500000 0.500000 0 4 0
( 10112 17792 -232 ) ( 10112 17408 -232 ) ( 10112 17408 -320 ) common/caulk 0 0 0 0.500000 0.500000 0 4 0
}
// brush 6
{
( 10496 17792 -776 ) ( 10112 17792 -776 ) ( 10112 17408 -776 ) common/caulk 0 0 0 0.500000 0.500000 0 4 0
( 10112 17408 -768 ) ( 10112 17792 -768 ) ( 10496 17792 -768 ) radiant_regression_tests/tile 0 0 0 0.500000 0.500000 0 0 0
( 10112 17408 -768 ) ( 10496 17408 -768 ) ( 10496 17408 -856 ) common/caulk 0 0 0 0.500000 0.500000 0 4 0
( 10496 17408 -768 ) ( 10496 17792 -768 ) ( 10496 17792 -856 ) common/caulk 0 0 0 0.500000 0.500000 0 4 0
( 10496 17792 -768 ) ( 10112 17792 -768 ) ( 10112 17792 -856 ) common/caulk 0 0 0 0.500000 0.500000 0 4 0
( 10112 17792 -768 ) ( 10112 17408 -768 ) ( 10112 17408 -856 ) common/caulk 0 0 0 0.500000 0.500000 0 4 0
}
}
// entity 1
{
"origin" "10312 17600 -480"
"classname" "info_player_deathmatch"
}
// entity 2
{
"light" "1000"
"origin" "10240 17608 -464"
"classname" "light"
}

View file

@ -0,0 +1,45 @@
DESCRIPTION OF PROBLEM:
=======================
The example map, maps/snap_plane.map, contains an example of some bugs.
The green brush with the red face is transformed into something totally
unexpected.
To trigger the bug, compile the map; you don't need -vis or -light. Only
-bsp (the first q3map2 stage) is necessary to trigger the bug. The only
entities in the map are a light and a info_player_deathmatch, so the map will
compile for any Q3 mod.
SOLUTION TO PROBLEM:
====================
I actually came up with this regression test after reading the code to
SnapPlane() and SnapNormal(). I decided to make this map as a test of
whether or not I understand how the code is broken. Sure enough, the map
is broken in the same way that I would expect it to be broken.
The problem is that the red face of the green brush in the center of the room
is very close to being axially aligned, but not quite. This plane will
therefore be "snapped" to become axial. This is not the problem. The
problem is that after the snap, the plane will be shifted a great deal,
and the corner of the green brush will no longer come even close to meeting
the corner of the other cube brush next to it (the two corners of the two
brushes will drift apart a great deal).
If you study the legacy SnapPlane() code, you will see that planes are
defined as a unit normal and distance from origin. Well, because
of the position of this brush on the side of the world extents (far from
the original), the snap will cause drastic effects on the points that the
plane was supposed to approximate.
Another problem with SnapPlane() is that SnapNormal() snaps too liberally.
Once SnapNormal() is changed to only snap normals that are REALLY close
to axial (and not anything within 0.25 degrees), this bug will no longer
appear, but the SnapPlane() problem will still be present. So, this
regression test should be fixed BEFORE SnapNormal() is fixed, otherwise
create another regression test with a red face that is much much closer to
being axially aligned. We want to make sure that SnapPlane() is fixed when
things actually do get snapped.
The code to address these issues is currently being worked on.

View file

@ -0,0 +1,89 @@
// entity 0
{
"classname" "worldspawn"
// brush 0
{
( -54784 5760 -64 ) ( -54976 5760 -64 ) ( -54976 5632 -64 ) radiant_regression_tests/tile 0 0 0 0.500000 0.500000 0 0 0
( -54976 5632 0 ) ( -54976 5760 0 ) ( -54784 5760 0 ) radiant_regression_tests/tile 0 0 0 0.500000 0.500000 0 0 0
( -54976 5632 0 ) ( -54784 5632 0 ) ( -54784 5632 -64 ) radiant_regression_tests/tile 0 0 0 0.500000 0.500000 0 0 0
( -54784 5632 0 ) ( -54784 5760 0 ) ( -54784 5760 -64 ) radiant_regression_tests/tile 0 0 0 0.500000 0.500000 0 0 0
( -54784 5760 0 ) ( -54976 5760 0 ) ( -54976 5760 -64 ) radiant_regression_tests/tile 0 0 0 0.500000 0.500000 0 0 0
( -54976 5760 0 ) ( -54976 5632 0 ) ( -54976 5632 -64 ) radiant_regression_tests/tile 0 0 0 0.500000 0.500000 0 0 0
}
// brush 1
{
( -53808 5616 -64 ) ( -55064 5616 -64 ) ( -55064 4944 -64 ) radiant_regression_tests/green 0 0 0 0.500000 0.500000 0 0 0
( -55072 4944 0 ) ( -55072 5616 0 ) ( -53816 5616 0 ) radiant_regression_tests/green 0 0 0 0.500000 0.500000 0 0 0
( -55040 4096 8 ) ( -53784 4096 8 ) ( -53784 4096 0 ) radiant_regression_tests/green 0 0 0 0.500000 0.500000 0 0 0
( -54272 4936 8 ) ( -54272 5608 8 ) ( -54272 5608 0 ) radiant_regression_tests/green 0 0 0 0.500000 0.500000 0 0 0
( -53816 5632 8 ) ( -55072 5632 8 ) ( -55072 5632 0 ) radiant_regression_tests/green 0 0 0 0.500000 0.500000 0 0 0
( -54784 5592 8 ) ( -54784 4920 8 ) ( -54784 4920 0 ) radiant_regression_tests/green 0 0 0 0.500000 0.500000 0 0 0
( -54528 5632 -64 ) ( -54272 5631 -64 ) ( -54528 5632 0 ) radiant_regression_tests/red 0 0 0 0.500000 0.500000 0 0 0
}
// brush 2
{
( -54200 5904 -128 ) ( -55032 5904 -128 ) ( -55032 5824 -128 ) common/caulk 0 0 0 0.500000 0.500000 0 4 0
( -55024 5824 192 ) ( -55024 5904 192 ) ( -54192 5904 192 ) common/caulk 0 0 0 0.500000 0.500000 0 4 0
( -55040 5824 0 ) ( -54208 5824 0 ) ( -54208 5824 -64 ) radiant_regression_tests/tile 0 0 0 0.500000 0.500000 0 0 0
( -54208 5824 0 ) ( -54208 5904 0 ) ( -54208 5904 -64 ) common/caulk 0 0 0 0.500000 0.500000 0 4 0
( -54200 5832 0 ) ( -55032 5832 0 ) ( -55032 5832 -64 ) common/caulk 0 0 0 0.500000 0.500000 0 4 0
( -55040 5904 0 ) ( -55040 5824 0 ) ( -55040 5824 -64 ) common/caulk 0 0 0 0.500000 0.500000 0 4 0
}
// brush 3
{
( -54144 5824 -128 ) ( -54208 5824 -128 ) ( -54208 5424 -128 ) common/caulk 0 0 0 0.500000 0.500000 0 4 0
( -54208 5424 192 ) ( -54208 5824 192 ) ( -54144 5824 192 ) common/caulk 0 0 0 0.500000 0.500000 0 4 0
( -54160 4032 192 ) ( -54096 4032 192 ) ( -54096 4032 -128 ) common/caulk 0 0 0 0.500000 0.500000 0 4 0
( -54200 5424 192 ) ( -54200 5824 192 ) ( -54200 5824 -128 ) common/caulk 0 0 0 0.500000 0.500000 0 4 0
( -54144 5824 192 ) ( -54208 5824 192 ) ( -54208 5824 -128 ) common/caulk 0 0 0 0.500000 0.500000 0 4 0
( -54208 5824 192 ) ( -54208 5424 192 ) ( -54208 5424 -128 ) radiant_regression_tests/tile 0 0 0 0.500000 0.500000 0 0 0
}
// brush 4
{
( -54208 4032 -128 ) ( -54760 4032 -128 ) ( -54760 3944 -128 ) common/caulk 0 0 0 0.500000 0.500000 0 4 0
( -54760 3944 192 ) ( -54760 4032 192 ) ( -54208 4032 192 ) common/caulk 0 0 0 0.500000 0.500000 0 4 0
( -54752 4024 192 ) ( -54200 4024 192 ) ( -54200 4024 -128 ) common/caulk 0 0 0 0.500000 0.500000 0 4 0
( -54208 3944 192 ) ( -54208 4032 192 ) ( -54208 4032 -128 ) common/caulk 0 0 0 0.500000 0.500000 0 4 0
( -54208 4032 192 ) ( -54760 4032 192 ) ( -54760 4032 -128 ) radiant_regression_tests/tile 0 0 0 0.500000 0.500000 0 0 0
( -55040 4016 192 ) ( -55040 3928 192 ) ( -55040 3928 -128 ) common/caulk 0 0 0 0.500000 0.500000 0 4 0
}
// brush 5
{
( -55040 5824 -128 ) ( -55256 5824 -128 ) ( -55256 5256 -128 ) common/caulk 0 0 0 0.500000 0.500000 0 4 0
( -55256 5256 192 ) ( -55256 5824 192 ) ( -55040 5824 192 ) common/caulk 0 0 0 0.500000 0.500000 0 4 0
( -55256 4032 192 ) ( -55040 4032 192 ) ( -55040 4032 -128 ) common/caulk 0 0 0 0.500000 0.500000 0 4 0
( -55040 5256 192 ) ( -55040 5824 192 ) ( -55040 5824 -128 ) radiant_regression_tests/tile 0 0 0 0.500000 0.500000 0 0 0
( -55040 5824 192 ) ( -55256 5824 192 ) ( -55256 5824 -128 ) common/caulk 0 0 0 0.500000 0.500000 0 4 0
( -55048 5808 192 ) ( -55048 5240 192 ) ( -55048 5240 -128 ) common/caulk 0 0 0 0.500000 0.500000 0 4 0
}
// brush 6
{
( -54208 4032 192 ) ( -55040 4032 192 ) ( -55040 4024 192 ) radiant_regression_tests/tile 0 0 0 0.500000 0.500000 0 0 0
( -55016 4024 200 ) ( -55016 4032 200 ) ( -54184 4032 200 ) common/caulk 0 0 0 0.500000 0.500000 0 4 0
( -55040 4032 296 ) ( -54208 4032 296 ) ( -54208 4032 192 ) common/caulk 0 0 0 0.500000 0.500000 0 4 0
( -54208 4024 296 ) ( -54208 4032 296 ) ( -54208 4032 192 ) common/caulk 0 0 0 0.500000 0.500000 0 4 0
( -54200 5824 296 ) ( -55032 5824 296 ) ( -55032 5824 192 ) common/caulk 0 0 0 0.500000 0.500000 0 4 0
( -55040 4032 296 ) ( -55040 4024 296 ) ( -55040 4024 192 ) common/caulk 0 0 0 0.500000 0.500000 0 4 0
}
// brush 7
{
( -54192 4560 -136 ) ( -55024 4560 -136 ) ( -55024 4552 -136 ) common/caulk 0 0 0 0.500000 0.500000 0 4 0
( -55040 4024 -128 ) ( -55040 4032 -128 ) ( -54208 4032 -128 ) radiant_regression_tests/tile 0 0 0 0.500000 0.500000 0 0 0
( -55040 4032 -128 ) ( -54208 4032 -128 ) ( -54208 4032 -256 ) common/caulk 0 0 0 0.500000 0.500000 0 4 0
( -54208 4024 -128 ) ( -54208 4032 -128 ) ( -54208 4032 -256 ) common/caulk 0 0 0 0.500000 0.500000 0 4 0
( -54208 5824 -120 ) ( -55040 5824 -120 ) ( -55040 5824 -248 ) common/caulk 0 0 0 0.500000 0.500000 0 4 0
( -55040 4032 -128 ) ( -55040 4024 -128 ) ( -55040 4024 -256 ) common/caulk 0 0 0 0.500000 0.500000 0 4 0
}
}
// entity 1
{
"light" "1000"
"origin" "-54664 5696 40"
"classname" "light"
}
// entity 2
{
"angle" "360"
"origin" "-54840 5696 88"
"classname" "info_player_deathmatch"
}