View Issue Details

IDProjectCategoryView StatusLast Update
0005580The Dark ModCodingpublic10.04.2021 04:40
Reporterstgatilov Assigned Tostgatilov  
Status resolvedResolutionfixed 
Product VersionTDM 2.09 
Target VersionTDM 2.10Fixed in VersionTDM 2.10 
Summary0005580: Dmap : better windings precision
DescriptionIt turned out that precision of all windings (brush sides, portals, nodes) is rather bad.

Several versions ago I added double precision to idWinding::Clip implementation, so intersections under low angle are still precise up to float32 representation precision.
However, the winding itself is still store with 32-bit floats.
This becomes a big problem because typical way to compute winding is to take huge quad with radius 256K and clip it by several planes:
    idWinding *mid = new idWinding( plane.Normal(), plane.Dist() );
    for ( i = 0; i < sides.Num() && mid; i++ ) {
        mid = mid->Clip( -sides[i]->plane, BRUSH_EPSILON, false );
This gives us a bit less than two digits of precision after decimal dot, regardless of map size.

This should be improved.
Additional InformationOriginally found when analyzing decal depth offsets issues.
See post on forum:
(From related problem 0004634)
TagsNo tags attached.


related to 0004634 assignedstgatilov Decal depth fighting (Inn Business: "rug in tavern is not smooth") 
related to 0005486 resolvedstgatilov dmap: close vertices due to numeric errors, and bloomed sparklies 




09.04.2021 14:04

administrator   ~0013827

The idea of fixing is to compute winding in two-pass algorithm:
  Pass 1: start from huge quad and clip it with all planes in order to get rough estimate of winding.
  Pass 2: take bounding box of rough estimate (on plane), expand it a bit and convert to winding, then clip it again with all planes

So pass 2 starts with a quad which surely contains the sought-for winding, but is almost as small as possible.
So the clipping on pass 2 gives most precision which is allowed by magnitude of coordinates.

Note that pass 1 can finish in empty winding, while the true precise answer is a small winding.
In order to avoid this problem, we can take the last non-empty winding as rough estimate.
Hopefully, this should avoid the problem of turning small winding into empty one in most cases.

Of course, such two-pass algorithm takes more time, but I think it is worth it.

Since it is rather complicated, it will be wrapped into a method of idWinding.
It will accept main plane of the desired winding, and a list of clipping/trimming planes.
Plus tolerance, and probably some flags saying what to do for clipping planes incident to the winding plane (drop such winding of ignore clip plane).


10.04.2021 04:39

administrator   ~0013833

Preliminary changes committed in:
  r9240. Inlined BaseWindingForNode into MakeNodePortal, both in dmap and in AAS code.
  r9241. Added method idWinding::CreateTrimmedPlane.

The actual behavior changes are committed in:
  r9242. Use idWinding::CreateTrimmedPlane in CreateBrushWindings (dmap).
  r9243. Use idWinding::CreateTrimmedPlane in MakeNodePortal (dmap).
  r9244. Use idWinding::CreateTrimmedPlane in SplitBrush (dmap).
  r9245. Use idWinding::CreateTrimmedPlane in idBrush::CreateWindings (aas).
  r9246. Use idWinding::CreateTrimmedPlane in idBrushBSPNode::Split (aas).
  r9247. Use idWinding::CreateTrimmedPlane in idBrushBSP::MakeNodePortal (aas).
  r9248. Use idWinding::CreateTrimmedPlane in idBrush::SplitImpl (aas).

Note that aside from precision changes (precision should now be better), there are some more changes in behavior:
  1) Both versions of MakeNodePortal used different tolerance when clipping with parent planes and with other portals' planes.
      Now they use same tolerance (the lower one).
  2) CreateBrushWindings now handles equal/opposite planes and singular windings differently.
      Previously dmap version removed winding if it completely belongs to clipping plane, although it was very unlikely to happen due to exactly zero tolerance.
      Previously aas version retained winding if it completely belonged to clipping plane, regardless of whether clipping plane is equal/opposite/not parallel at all.
      Now both versions kill winding in such case if clipping plane is not parallel (singular winding), kill it if clipping side is incident but opposite-oriented (thin brush), and retain if it is equal and same-oriented (very important for AAS with its ExpandForAxialBox and bevels).

Unfortunately, it is hard to implement a cvar which returns exactly the old behavior: it would need copy/pasting all the affected chunks of code.
So this change cannot be disabled in new code, even though it changes dmap behavior quite seriously.


10.04.2021 04:40

administrator   ~0013834

Combined with svn rev 9239 from 0005486, these changes fix decal depth fighting in test/

Issue History

Date Modified Username Field Change
09.04.2021 13:56 stgatilov New Issue
09.04.2021 13:56 stgatilov Status new => assigned
09.04.2021 13:56 stgatilov Assigned To => stgatilov
09.04.2021 13:57 stgatilov Additional Information Updated
09.04.2021 13:57 stgatilov Relationship added related to 0004634
09.04.2021 14:04 stgatilov Note Added: 0013827
09.04.2021 17:13 stgatilov Relationship added related to 0005486
10.04.2021 04:39 stgatilov Note Added: 0013833
10.04.2021 04:40 stgatilov Note Added: 0013834
10.04.2021 04:40 stgatilov Status assigned => resolved
10.04.2021 04:40 stgatilov Resolution open => fixed
10.04.2021 04:40 stgatilov Fixed in Version => TDM 2.10