Adding plane_aliasing regression test as promised in an email. I was able

to come up with this regression test, demonstrating the error, on my first
try.


git-svn-id: svn://svn.icculus.org/gtkradiant/GtkRadiant/branches/Rambetter-math-fix-experiments@410 8a3a26a2-13c4-0310-b231-cf6edde360e5
This commit is contained in:
rambetter 2011-01-05 05:43:57 +00:00
parent f5ebc52dca
commit 41470e6a03
6 changed files with 214 additions and 0 deletions

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"
}