Jump to content
Search In
  • More options...
Find results that contain...
Find results in...
zokum

Texture alignment conundrum with seg splits

Recommended Posts

I'm posting here since this is a very broad topic which I really would like to hear the ffedback from the entire community. I want to hear people's opinion on how to solve a problem with no real solution.

Here's some background to better explain the problem. Those familiar with Doom engine rendering and seg splits can skip this section.
 

Spoiler

Doom doesn't actually render linedefs, it renders segs. Segs are segments of a linedef. There can be many segs on one linedef, both on the front and back side. Extra segs are created when the BSP process cuts the geometry into two parts.

Seg splits are only problematic when the partition line or the seg are diagonal, due to rounding of vertex coordinates to integers.


When segs are split, the length can subtly changeby +/- ~1.1 pixels. This can lead to each seg becoming 1 pixel longer for each split. This means that a linedef might be 170 pixels inside the editor, but will be 172 pixels long in game.

ZokumBSP and possibly other nodebuilders currently compute the offset based on the seg, so multiple splits can increase the error even more. Due to some other changes I am changing the code to compute it based on the original linedef's origin, not the split seg. This leads to the following rare changes that can crop up in some corner cases.

1. Textures should be at most 1 pixel off by the end, they can no longer be off by number of segs pixels.
2. Textures can now gain repeating lines in the middle of textures.
3. Aligning diagonal textures will be easier, since textures are much less likely to be off at the linedef ends compared to the editor.
4. In many cases problematic walls can be cured by marking it as do-not-split. Then it will only be split if there is no other way to build the map.

This is a very rare occurence, and it almost never occurs. It should be noted that there will always be some wonkiness when splitting a seg. The question is, what kind of wonkiness is best?.

Here's some debug output from a build of Doom 2 MAP15:
 

Spoiler

SS   5, seg    0 Frontside offset:  256 |  256 (0)                                                                                                                                                                                                                              [130/1990]
SS  10, seg    2 Frontside offset:   32 |   32 (0)
SS  11, seg    4 Frontside offset:  240 |  240 (0)
SS  27, seg    1 Frontside offset:   13 |   13 (0)
SS  29, seg    0 Frontside offset:   69 |   69 (0)
SS  47, seg    5 Frontside offset:  320 |  320 (0)
SS  50, seg    2 Frontside offset:  448 |  448 (0)
SS  51, seg    0 Frontside offset:  512 |  512 (0)
SS  54, seg    1 Frontside offset:  632 |  632 (0)
SS  60, seg    3 Frontside offset:  256 |  256 (0)
SS  69, seg    5 Frontside offset:  384 |  384 (0)
SS  70, seg    1 Frontside offset:  720 |  720 (0)
SS  71, seg    1 Frontside offset:  512 |  512 (0)
SS  76, seg    3 Frontside offset:  320 |  320 (0)
SS  84, seg    3 Frontside offset:  416 |  416 (0)
SS  85, seg    0 Frontside offset:  688 |  688 (0)
SS  86, seg    1 Frontside offset:  480 |  480 (0)
SS  97, seg    5 Frontside offset:  288 |  288 (0)
SS 101, seg    3 Frontside offset:  448 |  448 (0)
SS 102, seg    1 Frontside offset:  720 |  720 (0)
SS 103, seg    1 Frontside offset:  512 |  512 (0)
SS 106, seg    0 Frontside offset:  160 |  160 (0)
SS 107, seg    0 Frontside offset:  687 |  687 (0)
SS 108, seg    0 Frontside offset:   32 |   32 (0)
SS 111, seg    0 Backside  offset:   48 |   48 (0)
SS 113, seg    2 Backside  offset:  112 |  112 (0)
SS 115, seg    1 Frontside offset:  260 |  260 (0)
SS 125, seg    3 Frontside offset:  324 |  324 (0)
SS 127, seg    2 Frontside offset:   16 |   16 (0)
SS 130, seg    2 Backside  offset:   64 |   64 (0)
SS 135, seg    0 Frontside offset:    8 |    8 (0)
SS 135, seg    1 Frontside offset:  181 |  181 (0)
SS 136, seg    3 Frontside offset:  240 |  240 (0)
SS 137, seg    1 Frontside offset:   16 |   16 (0)
SS 139, seg    4 Frontside offset:   40 |   40 (0)
SS 140, seg    0 Frontside offset:   16 |   16 (0)
SS 146, seg    1 Frontside offset:   64 |   64 (0)
SS 151, seg    0 Frontside offset:   40 |   40 (0)
SS 153, seg    1 Backside  offset:   64 |   64 (0)
SS 154, seg    1 Frontside offset:   72 |   72 (0)
SS 158, seg    1 Frontside offset:  192 |  192 (0)
SS 159, seg    1 Frontside offset:  160 |  160 (0)
SS 162, seg    1 Frontside offset:  240 |  240 (0)
SS 163, seg    0 Frontside offset:  208 |  208 (0)
SS 165, seg    0 Frontside offset:   64 |   64 (0)
SS 171, seg    1 Frontside offset:  160 |  160 (0)
SS 174, seg    1 Backside  offset:   16 |   16 (0)
SS 174, seg    2 Backside  offset:   16 |   16 (0)
SS 176, seg    0 Backside  offset:   16 |   16 (0)
SS 181, seg    0 Frontside offset:   96 |   96 (0)
SS 183, seg    0 Frontside offset:  152 |  152 (0)
SS 188, seg    1 Frontside offset:   48 |   48 (0)
SS 193, seg    1 Frontside offset:   48 |   48 (0)
SS 195, seg    1 Frontside offset:  112 |  112 (0)
SS 196, seg    2 Frontside offset:   64 |   64 (0)
SS 205, seg    5 Frontside offset:   64 |   64 (0)
SS 209, seg    5 Frontside offset: 1648 | 1648 (0)
SS 210, seg    0 Frontside offset:  304 |  304 (0)
SS 213, seg    1 Backside  offset:   96 |   96 (0)
SS 217, seg    0 Backside  offset:   68 |   68 (0)
SS 217, seg    2 Backside  offset:  560 |  560 (0)
SS 224, seg    0 Frontside offset:  181 |  181 (0)
SS 227, seg    1 Frontside offset:  192 |  192 (0)
SS 228, seg    0 Frontside offset:  448 |  448 (0)
SS 229, seg    0 Frontside offset:  160 |  160 (0)
SS 230, seg    1 Frontside offset:   64 |   64 (0)
SS 232, seg    0 Frontside offset:  416 |  416 (0)
SS 236, seg    0 Frontside offset:  352 |  352 (0)
SS 240, seg    0 Frontside offset:  288 |  288 (0)
SS 243, seg    1 Frontside offset:  512 |  512 (0)
SS 244, seg    0 Frontside offset:  384 |  384 (0)
SS 245, seg    1 Backside  offset:   64 |   64 (0)
SS 247, seg    2 Backside  offset:  128 |  128 (0)
SS 248, seg    0 Frontside offset:  256 |  256 (0)
SS 251, seg    0 Frontside offset:  544 |  544 (0)
SS 251, seg    2 Frontside offset:  128 |  128 (0)
SS 252, seg    0 Frontside offset:  288 |  288 (0)
SS 253, seg    0 Frontside offset:  160 |  160 (0)
SS 254, seg    0 Backside  offset:   64 |   64 (0)
SS 256, seg    0 Backside  offset:   64 |   64 (0)
SS 258, seg    1 Backside  offset:  128 |  128 (0)
SS 268, seg    0 Backside  offset:   64 |   64 (0)
SS 269, seg    1 Backside  offset:   64 |   64 (0)
SS 270, seg    1 Backside  offset:   64 |   64 (0)
SS 271, seg    0 Backside  offset:  736 |  736 (0)
SS 274, seg    0 Backside  offset:  940 |  940 (0)
SS 283, seg    2 Frontside offset:  302 |  303 (-1)
SS 285, seg    2 Frontside offset:  101 |  101 (0)
SS 287, seg    1 Backside  offset:  160 |  160 (0)
SS 289, seg    2 Backside  offset:   64 |   64 (0)
SS 293, seg    0 Frontside offset:  128 |  128 (0)
SS 297, seg    1 Backside  offset:  288 |  288 (0)
SS 298, seg    0 Frontside offset:  128 |  128 (0)
SS 298, seg    3 Backside  offset:  128 |  128 (0)
SS 304, seg    2 Frontside offset:   22 |   23 (-1)                                                                                                                                                                                                                              [36/1990]
SS 305, seg    0 Backside  offset:  320 |  320 (0)
SS 305, seg    4 Frontside offset:  128 |  128 (0)
SS 314, seg    1 Backside  offset:   80 |   80 (0)
SS 334, seg    2 Frontside offset:   48 |   48 (0)
SS 342, seg    0 Frontside offset:   56 |   56 (0)
SS 343, seg    0 Backside  offset:  128 |  128 (0)
SS 345, seg    0 Backside  offset:  288 |  288 (0)
SS 346, seg    1 Backside  offset:  128 |  128 (0)
SS 348, seg    1 Frontside offset:  879 |  879 (0)
SS 349, seg    2 Frontside offset:  115 |  115 (0)
SS 351, seg    1 Frontside offset:  558 |  558 (0)
SS 352, seg    1 Backside  offset:   64 |   64 (0)
SS 359, seg    3 Frontside offset:  128 |  128 (0)
SS 360, seg    0 Backside  offset:   64 |   64 (0)
SS 389, seg    0 Frontside offset:   64 |   64 (0)
SS 391, seg    0 Frontside offset:  104 |  104 (0)
SS 392, seg    0 Frontside offset:  156 |  156 (0)
SS 400, seg    0 Backside  offset:  154 |  154 (0)
SS 403, seg    1 Frontside offset:  160 |  160 (0)
SS 404, seg    2 Frontside offset:  192 |  192 (0)
SS 406, seg    1 Backside  offset:   72 |   72 (0)
SS 407, seg    0 Frontside offset:   24 |   24 (0)
SS 408, seg    0 Backside  offset:   16 |   16 (0)
SS 411, seg    0 Frontside offset:   40 |   40 (0)
SS 412, seg    0 Backside  offset:   56 |   56 (0)
SS 415, seg    1 Backside  offset:  112 |  112 (0)
SS 416, seg    0 Backside  offset:   96 |   96 (0)
SS 421, seg    2 Frontside offset:  136 |  136 (0)
SS 435, seg    3 Frontside offset:   32 |   32 (0)
SS 442, seg    0 Frontside offset:  128 |  128 (0)
SS 469, seg    1 Frontside offset:   61 |   61 (0)
SS 477, seg    3 Frontside offset:   64 |   64 (0)
SS 486, seg    1 Frontside offset:   80 |   80 (0)
SS 486, seg    2 Frontside offset:   56 |   56 (0)
SS 497, seg    0 Frontside offset:   12 |   13 (-1)
SS 498, seg    0 Frontside offset:  149 |  148 (1)
SS 507, seg    0 Backside  offset:  414 |  414 (0)
SS 510, seg    0 Backside  offset:  504 |  504 (0)
SS 513, seg    2 Frontside offset:   96 |   96 (0)
SS 515, seg    1 Frontside offset:  192 |  192 (0)
SS 517, seg    0 Backside  offset:  290 |  290 (0)
SS 517, seg    1 Frontside offset:  419 |  419 (0)
SS 527, seg    0 Frontside offset:   40 |   41 (-1)
SS 528, seg    1 Frontside offset:   40 |   40 (0)
SS 534, seg    0 Frontside offset:  128 |  128 (0)
SS 537, seg    0 Frontside offset:   64 |   64 (0)
SS 538, seg    0 Frontside offset:   64 |   64 (0)
SS 539, seg    0 Frontside offset:  128 |  128 (0)
SS 541, seg    0 Frontside offset:  192 |  192 (0)
SS 542, seg    0 Frontside offset:  256 |  256 (0)
SS 543, seg    1 Frontside offset:  256 |  256 (0)
SS 550, seg    0 Frontside offset:  297 |  297 (0)
SS 556, seg    0 Frontside offset:  181 |  181 (0)
SS 557, seg    2 Frontside offset:  107 |  107 (0)
SS 559, seg    0 Frontside offset:  166 |  166 (0)
SS 562, seg    0 Frontside offset:  147 |  147 (0)
SS 564, seg    4 Backside  offset:  232 |  232 (0)
SS 567, seg    3 Backside  offset:   24 |   24 (0)
SS 568, seg    2 Backside  offset:   40 |   40 (0)
SS 569, seg    1 Backside  offset:   24 |   24 (0)
SS 571, seg    1 Backside  offset:    8 |    8 (0)
SS 584, seg    0 Frontside offset:    8 |    8 (0)
SS 589, seg    0 Frontside offset:    8 |    8 (0)
SS 589, seg    2 Frontside offset:    9 |    9 (0)
SS 594, seg    0 Frontside offset:    7 |    7 (0)
SS 595, seg    2 Backside  offset:   56 |   56 (0)
SS 596, seg    0 Frontside offset:   16 |   16 (0)
SS 598, seg    0 Frontside offset:   24 |   24 (0)
SS 598, seg    2 Frontside offset:   22 |   22 (0)
SS 603, seg    0 Backside  offset:   16 |   16 (0)
SS 605, seg    0 Backside  offset:   80 |   80 (0)
SS 606, seg    1 Backside  offset:   80 |   80 (0)
SS 607, seg    2 Backside  offset:   80 |   80 (0)
SS 608, seg    1 Frontside offset:  120 |  120 (0)
SS 610, seg    2 Frontside offset:  110 |  110 (0)
SS 611, seg    0 Frontside offset:   88 |   88 (0)
SS 617, seg    0 Frontside offset:   44 |   44 (0)
SS 619, seg    0 Frontside offset:  132 |  132 (0)
SS 620, seg    0 Frontside offset:  248 |  248 (0)
SS 622, seg    0 Frontside offset:   32 |   32 (0)
SS 628, seg    0 Frontside offset:   80 |   80 (0)
SS 640, seg    4 Frontside offset:   35 |   35 (0)
SS 656, seg    0 Frontside offset:   85 |   86 (-1)
SS 657, seg    0 Backside  offset:  772 |  772 (0)
SS 670, seg    4 Frontside offset:   64 |   64 (0)
SS 688, seg    0 Frontside offset:   40 |   40 (0)
SS 690, seg    3 Frontside offset:  120 |  120 (0)
SS 694, seg    0 Frontside offset:  163 |  163 (0)
SS 697, seg    0 Frontside offset:   74 |   74 (0)
SS 700, seg    2 Frontside offset:   61 |   61 (0)
SS 704, seg    0 Frontside offset:  194 |  194 (0)
SS 707, seg    0 Frontside offset:  210 |  210 (0)
SS 711, seg    0 Frontside offset:   27 |   27 (0)
SS 713, seg    0 Frontside offset:  185 |  186 (-1)
SS 721, seg    0 Backside  offset:   79 |   80 (-1)
SS 726, seg    1 Frontside offset:  144 |  144 (0)
SS 730, seg    1 Backside  offset:  181 |  180 (1)
SS 731, seg    0 Backside  offset:   86 |   86 (0)
SS 740, seg    3 Backside  offset:   20 |   20 (0)
SS 743, seg    3 Frontside offset:    8 |    8 (0)
SS 745, seg    0 Frontside offset:   69 |   68 (1)
SS 746, seg    0 Frontside offset:   49 |   49 (0)
SS 748, seg    0 Frontside offset:  160 |  160 (0)
SS 749, seg    0 Frontside offset:  128 |  128 (0)
SS 750, seg    1 Frontside offset:   16 |   16 (0)
SS 762, seg    0 Backside  offset:   32 |   32 (0)
SS 763, seg    2 Backside  offset:  128 |  128 (0)
SS 764, seg    0 Frontside offset:  128 |  128 (0)
SS 775, seg    2 Frontside offset:  256 |  256 (0)
SS 776, seg    0 Frontside offset:  253 |  254 (-1)
SS 777, seg    2 Frontside offset:  160 |  160 (0)
SS 778, seg    0 Backside  offset:  160 |  160 (0)
SS 780, seg    2 Backside  offset:   64 |   64 (0)
SS 783, seg    0 Backside  offset:  320 |  320 (0)
SS 784, seg    0 Backside  offset:  288 |  288 (0)
SS 786, seg    1 Frontside offset:  106 |  106 (0)
SS 786, seg    2 Frontside offset:  929 |  929 (0)
SS 787, seg    0 Frontside offset:  105 |  106 (-1)
SS 788, seg    2 Frontside offset:  476 |  476 (0)
SS 789, seg    2 Frontside offset:  412 |  412 (0)

 


I haven't checked, maybe some engine freak can correct me if I am wrong. When rendering diagonal lines, it can render the last "pixel" as a less wide column. This means that some pixel columns today will be "wider" or "narrower" depending on the rounding in the seg, since a seg ends on a non-integer pixel coordinate, but the new one starts on an integer value. Values below 0.5 pixels get round down, we get a "wide" pixel colum since it renders say 0.4 of a column, then 1.0 of the same column in the new seg, giving us 1.4 columns worth of the same pixels. It at least looks like that on the diagonal grey big brick walls on map15.

So what do you guys and gals think? Is this more or less correct than the old method?

Edited by zokum

Share this post


Link to post
29 minutes ago, zokum said:

When rendering diagonal lines, it can render the last "pixel" as a less wide column

That sounds overly simplistic.  The camera angle is almost never going to be *perfectly* perpendicular to a diagonal wall, but if it were, and the distance was right so that each column in a texture corresponding to 3 screen pixels (say), then I don't think you would see the right-most pixel being narrower than the rest.  Rather I think it will be quite random which columns of the texture will be rendered wider or narrow than others.  Especially when you add perspective into the mix, where the texture column is not a linear function of the on-screen X coordinate.

 

 

 

Share this post


Link to post

This is actually quitre easy to find in many maps. Here's from the end of the long diagonal wall on d2 map15. You can find plenty of such oddities if you just know where to look and what to look for. This is taken in prboom-plus, but it shows up in chocolate doom as well. It's visible from a wide range of locations near the "corner".

map15-narrow-column.png

Share this post


Link to post

Here's an example of a column of pixels that is like 0.8 of a pixel or so. Very easy to locate. The point is. The more a seg is split, the more the rendered length can deviate from the expected length. The question is, how should it be handled when lines become longer?

It should be noted that it might be possible that splits cancel out the effect of eachother. Anything below 0.5 will be rounded down.

map15-narrow-column2.png

Share this post


Link to post

But don't those cut-off pixels also happen if there's only one seg for the linedef? If a linedef is only, say, ~90.51 units long (i.e. the hypotenuse of a right triangle with 64 units long catheti), isn't it expected to see half a pixel drawn?

 

Thinking about it, shouldn't we see wider/narrower pixels where the segs of a linedef meet? If we have a setup like this:

 

grafik.png.27a63413905d807c9c251c37551145a8.png

 

There will be a split along the short linedef. The "real" intersection of the lines will be at 15.574144486692013/1.9467680608365043, but the new vertex will be created at 16/2. That will make the shorter seg ~16.12 units long, the longer seg will have an offset of 16. So I'd expect to see 0.12 pixels of the 17th pixel where the segs meet, and then the 16th pixel again where the 2nd seg starts. but that doesn't seem to be the case, at least visually.

Share this post


Link to post

We probably do see mid-linedef-half pixels, but it's a very rare occurence. I can't remember any, but I haven't looked for them. The second screenshot is a 1-seg-cutoff.

The problem I am talking about is that several seg splits CAN lead to more than that 0.5 pixel difference. That's when aligning can end up looking odd. In many cases it's hard to spot since different linedefs often change texture, making the alignement problem non-existant.

In your example I presume there won't be any split, unless you have a normal texture on that loose linedef. Lines where the back and front side belong to the same sector can't render upper or lower textures, and get removed from the BSP tree unless they have a normal texture, a common optimization.

I'll go scour map15 and see if I can't find a mid-linedef-non-integer-pixel. Might be hard though, since doombsp gets the angle wrong, that might null out the effect a bit, but that also leads to otger errors like the map09 star problem.

Share this post


Link to post

Here's a mid-lindedef-seg-alignment-anomaly. Took me a few inutes to find. These errors do not show up in prboom+, but they are quite visible in Chocolate Doom. I browsed through the list of segs in slade 3 and found one where the offset was 21 on the front side, looked it up in an editor and went and looked in Doom and took some screenshots. The shot is from the inaccessible lava area in the exit area, roughly facing the exit teleporter. The third show is thre to show it's visible from multiple locations and different angles, and to make it easier to find the spot yourself. The seg split is at 21 units into linedef 1500.

There's also an additional anomaly that sometimes turns up due to rounding errors, shown in the second screenshot. This anomaly is visible from a multitude of angles and flickers in and out of the rendering when you move around. This isn't very pretty. Maybe avoiding splitting diagonal lines on problematic rounding points or in general should be a nodebuilder option?

15seg01.png

15seg02.png

15seg03.png

Share this post


Link to post

Here's what the end of the line looks like. There's a clear difference between Prboom+ and Chocolate Doom here. I might have changed the alingment if I playtested this in prboom, but I would probably have let it be if I tested with Chocolate Doom. Chocolate Doom is the top one. The shots aren't from the exact same position, but it's near enough.

map15-seg-end-difference.png

Share this post


Link to post

Here's the last file in this saga, I think it's fairly well documented by now. It's a 4 kilobyte recording of me going straight to such a seg split on map01. I recorded it in Chocolate Doom, this will not show up in PrBoom+ and most likely won't show up in many other ports either. http://doom2.net/zokum/demos/d2split.lmp

I think that in most cases, these splits aren't noticable in normal gameplay. If you're unlucky to get such a split it in a spot with a big change in color, brightness, lettering, etc, they might be a problem if you're really picky. I plan to one day add an option to try to build maps without this type of split, so they occur a lot less or not at all. I think it would be a worthwhile addition to a nodebuilder. They're usually not too hard to find with slade. These splits tend to have the occasional strip of pixels from the neighbouring column as well. This column might be related to bad seg angles, I haven't checked.

If anyone ever has weird texture issues on diagonal walls, point them to this thread. This effect here might just be the culprit. They're not too hard to fix either, just tag the wall with do-not-split.

Share this post


Link to post

So what would happen if you grew every diagonal seg by 1 unit on each end of the seg? Cause I'm thinking that the worst renderer issue is not the extra slivers, but in fact slime trails. I'm wondering if grow each diagonal seg would eliminate slime trails.

 

I think you're chasing your tail if you're trying to make a solution that works in both PrBoom and Chocolate, because PrBoom code adds fixes to try to prevent some rendering issues.

 

As a side note, be sure to turn off PrBoom's "Reduce Slime Trails" option during your testing, because that option moves the endpoints of the segs together to try to eliminate slime trails, though it's only somewhat effective. But it's most likely messing up your off-by-1 testing, I would imagine.

 

Definitely, if you had an option to avoid splitting diagonals, life would be great. But how often would it be possible to eliminate splitting a diagonal?

 

I imagine that if you *really* wanted some punishment, you could do a rigorous study of the Doom renderer, and gain a fantastic understanding of exactly what the effects are of each specific angle of seg splitting. But that's an enormous amount of work, I would think.

 

Unfortunately, you've got a lot of things working against you. The fixed-point math used in Doom's renderer is going to exasperate the off-by-1 issue, simply by moving closer to the wall. And, being able to change output resolution does the same thing. Probably, your best bet is to match what other node builders do, simply because that's what everyone has traditionally tested their maps with. (If they noticed a problem, they adjusted their map and rebuilt.) Any changes you introduce might upset a rebuild of those maps (but would be ok for new map development.)

 

Please continue to post your findings!

Share this post


Link to post

Actually, the precision of the fixed point in doom is more than adequate. It's the lack of precision in seg offesets that is the main problem. Those are integer numbers. That means that if a wall is split after 160.45 pixels, the next segment will start at 160 pixels. This is what gives those "wide" pixels. It's rendering 0.45 worth of game units then another 1.0 with the same pixel data.

This is a problem that CAN be mitigated by avoiding splits that lead to big roundoff errors. There are plenty of cases where the roundoff error will be none or so small that the split won't be noticable.

As for doing what the other nodebuilders do, I disagree. There hasn't been that much focus on such problems. All nodebuilders used to sometimes get the angles wrong etc. When it comes to mapping, adding and changing a map can lead to big changes in where things are split. I wouldn't worry about odd splits or slime trails until I get to the final version of a map. Only then should you consider adjustments to reduce these problems.

Adding bad splits as a criteria is def. something I plan to add to ZokumBSP. If you used the multi-tree algorithm, making it pick least rounding error as a 3rd criteria wouldn't be too hard. If two trees have the same amount of splits and subsectors, pick the one with the smallest rounding error.

Share this post


Link to post
1 hour ago, zokum said:

Actually, the precision of the fixed point in doom is more than adequate. It's the lack of precision in seg offesets that is the main problem. Those are integer numbers. That means that if a wall is split after 160.45 pixels, the next segment will start at 160 pixels. This is what gives those "wide" pixels. It's rendering 0.45 worth of game units then another 1.0 with the same pixel data.

I wish that were true. All of these issues can be traced to lack of precision. My point was that inadequate precision is in each step, which means that splitting diagonals will be problematic from all directions in all stages. Simply changing player position and orientation introduces texturing inaccuracies caused by low precision. Therefore, finding the "sweet spots" of which segs and angles are least problematic is going to be a challenge, with limited success.

 

1 hour ago, zokum said:

As for doing what the other nodebuilders do, I disagree. There hasn't been that much focus on such problems. All nodebuilders used to sometimes get the angles wrong etc. When it comes to mapping, adding and changing a map can lead to big changes in where things are split. I wouldn't worry about odd splits or slime trails until I get to the final version of a map. Only then should you consider adjustments to reduce these problems.

It would only matter for someone rebuilding an already tweaked map. Mappers stop tweaking when they are satisfied with the results. If they were to, then, use a builder that uses different algorithms, it could render their tweaks useless. This is a rare use case, because, if they are satisfied, why would they rebuild the map? But you did ask what the most appropriate method would be. Thinking about it again, I would suggest prioritizing the result as follows, in this order:

1. Do what looks best

2. Do what other ports do

 

One probably excludes the other.

 

Share this post


Link to post

I haven't actually checked, but some of the perceived problems with splits might be due to the fact that DoomBSP, ZenNode and BSP all compute the angles of split lines incorrectly. These walls might look better with correct angles stored in the seg. The errors are quite huge in some cases, map09 star structure being a good example.

My goal is to let people build maps well from the start, and only have to resort to tweaking if something odd shows up. There are so many known bugs / inefficiencies in BSP / ZenNode, that I wouldn't use them. I haven't looked at other node builders, maybe i should.

Share this post


Link to post
5 hours ago, zokum said:

I haven't actually checked, but some of the perceived problems with splits might be due to the fact that DoomBSP, ZenNode and BSP all compute the angles of split lines incorrectly. These walls might look better with correct angles stored in the seg. The errors are quite huge in some cases, map09 star structure being a good example.

Now, this I'm sure of - you proved the map09 issue. I was really hoping that this issue had been widespread...so map rebuilds would fix problems everywhere. It would be a neat thing to study with an archive batch rebuild approach, but that's a lot of work!

 

5 hours ago, zokum said:

My goal is to let people build maps well from the start, and only have to resort to tweaking if something odd shows up. There are so many known bugs / inefficiencies in BSP / ZenNode, that I wouldn't use them. I haven't looked at other node builders, maybe i should.

This is absolutely a noble goal. Did you ever consider the "grow the diagonal segs by 1 unit on each end" idea? Did I miss your response to that, or is it simply a bad idea? (I honestly don't know - it was just a two-minute hack idea.)

Share this post


Link to post

I haven't actually tried it, it's a neat idea IF it works. I have a hunch it will be pretty messy when it comes to rendering order. Still, it's something I ought to play around with, just to see what happens. Thise map09 issue is very widespread. It can be found in pretty much every map in the original game.

Share this post


Link to post

If it actually does work, the next step would be to only add a unit as needed (like when a diagonal split yields a large fractional component.)

 

Here's an interesting test: Make a map with all 45-degree diagonal lines, and always do splits perpendicular to those lines. That should produce either clean cuts, or 0.5 fractional cuts. If those can be made to render properly, I would think you'd have a shot at doing great things with arbitrary angles.

 

I wish I had time to play with this stuff - I'm jealous!

Share this post


Link to post

I need to actually make the time to catch up on all the posts in this thread to be relevant to the conversation, but these were my initial thoughts on this when i first saw the pics explaining what zokum was referring to, as well as the OP:

 

On 10/13/2018 at 3:28 AM, zokum said:

When segs are split, the length can subtly changeby +/- ~1.1 pixels. This can lead to each seg becoming 1 pixel longer for each split. This means that a linedef might be 170 pixels inside the editor, but will be 172 pixels long in game.

 

...

 

I haven't checked, maybe some engine freak can correct me if I am wrong. When rendering diagonal lines, it can render the last "pixel" as a less wide column. This means that some pixel columns today will be "wider" or "narrower" depending on the rounding in the seg, since a seg ends on a non-integer pixel coordinate, but the new one starts on an integer value. Values below 0.5 pixels get round down, we get a "wide" pixel colum since it renders say 0.4 of a column, then 1.0 of the same column in the new seg, giving us 1.4 columns worth of the same pixels. It at least looks like that on the diagonal grey big brick walls on map15.

 

Honestly I'm not sure about the engine adding more than an extra pixel on the ends of nonorthogonal lines, (even from multiple splits) though I'm very familiar with seeing fractions of pixels displayed on the right ends of lines who's widths are fractional, either due to placed vertices or segs, but I guess I just always looked at that as the logical way rendering would have to work, starting from the left and rendering all pixels until a vertex/seg cuts them off at an arbitrary point. The only cases to me where this is unfortunate are cases where the extra pixel is like .2 wide or less, leaving a sliver that can sometimes look slime-trail-ish at first glance. My thought on it was related to resolution, so with programs like prboom displaying higher resolutions we can typically see them easier. I also note that, much like slime trails, a lot of these, in particular the ones that are teeny tiny small, can only be seen from certain positions/angles, likely due to display res at that point tho.

 

This does also bring me to another point, unrelated a bit though, that this is one reason I can't use dbx as my main map making software, as it doesn't seem to show these at all in-editor, which is highly inaccurate compared to in-game and makes texture frankensteinery time-consuming and frustrating, which is a shame given how needed that can be for some nonorthogonal texturing. Point related to this topic: if you're using dbx it may make this a bit more confusing. Db2 and gzdb both display textures accurately for this, minus any segs created from nodebuilding. 

 

I've never known of or noticed the engine adding more than a full pixel to a given linedef though; perhaps the issue is too rare and requires long lines not already split by the author adding vertices that I simply haven't been lucky enough to draw that lottery, but I do this type of stuff all the time:

GFVaUiB.png

 

on nonorthogonal walls, so I'm very interested in this topic, especially as it pertains to your node builder. I'll have to make more time to read through this thread later though so hopefully my limited input can be more relevant to the conversation, but this is a great topic I wish more knowledgeable people would comment on.

Share this post


Link to post

I'll explain how it can add more pixels. Let's say we have a line that is diagonal and 256 pixels long. It gets split in two, one segment is now 120.6 pixels long, another is 136.4 pixels long. With seg 1 ending at 120.6, the next seg then gets an offset of 121, since that is closer. That means that by the end of the second segment the lasst pixels are the 257th and 0.4ths of the 258th pixel. The wall has grown by 1.4 pixels. Some due to the segmens being longer due not taking a straight path, and some due to the rounding upwards.

Imagine the second segment got split once more, adding another 1-2 pixels. Suddenly a wall that was initially 256 units long is now 259 pixels long. The rounding can work in favor of the length though, rounding both up and down, so in many cases one could end up with a wall that is roughly correct. On average though one should expect the lines to get longer, since the two segmens are no longer the shortest possible path from the original wall linedef.

As long as the added length is below 0.5 pixels, the texture roundoff will counteract this added length by rendering those "fat" pixels near the segment split. We end up with a longer wall, but also a slightly stretched texture.

All my code does is to compute the "stretch" as if it was only ever split into two segments. Multiple segments might lead to oddiities in the rendering in the middle of the wall, but the end of the wall should be fairly close to what was expected. When you're making things like doors or other walls with a well-defined tiling pattern, not having a lot of stray pixels is important. For other types of walls, like a stone wall ending in a 90" corner, this might not matter at all. Maybe it could be something you could set in the editor to gain control over the algorithm used, in case a wall is split.

The map01 split in the demo is pretty obvious, there are other on map01, they're not hard to find once you know what to look for. There's one one the diagonal wall near the exit to the outside area. The texture used makes it hard to spot.

Share this post


Link to post

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×