Tutorial: T-Junctions


(Ifurita) #1

Overview
T-junctions? WTF? So i set out to find out what these are and how to control them. I started out with the screenshots originally posted by Chavo One and a test map tutorial from Detoeni. Based on those two resources, I built a test map which I used to test tris count in a room built 5 different ways to test the effect on tris count. The following commentary/tutoria is paraphrased from posts by Ydnar and Chavo One and feedback from ReyalP and Detoeni. Enjoy.

Original post and discussion can be found at the WWGN forums: http://www.worldwidegaming.org/modules.php?name=Forums&file=viewtopic&t=23

What is a t-junction?
A t-junction occurs where ever a vertex meets an edge. Here’s an example using Room 1 of the test map, which is constructed pretty poorly. You’ll notice that there are a lot of t-junctions, which results in a lot of tris.

The 3 white arrows point at specific t-junctions. You can quickly compare those t-junctions with the screenshot to see how the engine breaks up, what looks like one brush, into many trianges. In the case of the floor, which is a single brush in radiant, it gets turned into ~20 tris due to the way the room is constructed.

Why do t-junctions result in additional triangle splits?
The compiler creates additional vertices to remove t-junction, which, left alone, which would cause a crack (sparklie) due to hardware FP imprecision.

How do I eliminate t-junctions from my map?
The only way to avoid them is to become aware of what causes them and map to avoid them, usually by not putting lots of brush corners adjacent to longer brush edges, hence this tutorial

It seems like a lot of work to get rid of all t-junctions. Do I really need to eliminate all of them?
Before you go wild cutting everything up to get the minimum number of t-junctions, consider if you need to. If your r_speeds in a particular area are not an issue, then there really isn’t a good reason to put a lot of effort into it. Also, reducing t-junctions can increase costs in other areas. Non-axial brushwork adds slightly to bsp size (a brush always has a full set of axial planes), and extra brushes will likely add to runtime cost, as they are used in physics. These things shouldn’t be an issue on most maps, but the point is that it isn’t entirely ‘free’. Also keep in mind, that as you better understand where t-junctions occur, you will naturally map to avoid them or optimize tris count, much like many mappers automatically miter walls when two brushes meet.

Results

Note: all tris counts were taken by standing on the light, centering my crosshair on the eagle, then setting cg_draw2d to 0

Room 1: Poor construction, no optimization – 530 tris
Room 2: Mitered door and window frames – 510 tris
Room 3: Tried to improve tris by restructuring the way I cut up the walls for the windows – 496 tris
Room 4: Mitered the walls to control how it was being broken up into tris – 470 tris
Room 5: Clipped floor to control how floor was being split - 468 tris

Overall improvement 62 tris (11.7%).

Screenies
For each room, I’ll give a screen cap from Radiant so that you can see what the brushwork looks like and an in-game screen with r_showtris 1 and r_speeds 1

Room 1 – Overall poor construction

Room 2 – Mitered the door and window frames

Room 3 – Restructured the way walls were cut up to make room for the windows and frames. Tried to keep the number of t-junctions at the floor to a minimum

Room 4 – Mitered walls to control how walls were cut up as well as moving the pillars off the wall and slightly into the room

Room 5 – Manually split floor into triangles to minimize tris count. You can see that i no longer have a bunch of vertices in the middle of the floor

Additional Notes

If you look at room 4 in Radiant, you will notice that the floor texture extends under the walls. The inside verticies of the walls shouldn’t cause t-junctions, because they aren’t on an edge, right? Wrong. Because both the wall and the floor are structural brushes, the parts completely hidden are eliminated at compile time, so the inside of the wall is effectively the edge of the textured area, and t-junctions are still generated. If the walls and floor were detail, the hidden parts would not be eliminated, and the t-junctions would not be created. This would cause z-fighting and overdraw where the walls met the floor.

Also notice that the floor in rooms 4 and 5 is not broken up around the freestanding pillars. This means there is overdraw and potential z-fighting below them. You could, of course, cut up the floor to avoid this (at the cost of more brushes and tris), but again, it probably isn’t worthwhile.

Test Map
Here is the test map. You’ll have manually load the map using /devmap t_junctions and to use no_clip to get from room to room

http://www.planetwolfenstein.com/4newbies/t_junctions.zip

Comments and suggestions are welcome.


(DWM|Commando) #2

wow, very good tutorial, the screns help so much, it really shows you how effective they are. good job, i will gretly consider t-count when ido my next map


(SCDS_reyalP) #3

Its worth mentioning that q3map doesn not create t-junctions for patch meshes. Indeed, it couldn’t, because their verticies are created at run time depending on distance and settings. Dealing with this should be the subject of it’s own tutorial.


(Ifurita) #4

IMO, and it’s something that Detoeni pointed out in his feedback, about they way he maps, is that you can most effectively control t-junctions and overdraw, when you really understand how it works and why it happens well enough to incoporate it into your basic mapping work, much like most people have figured out how to take vis into account when they lay out basic brushwork.


(-Ironman-) #5

damn i din’t understand much, but i think i have to understand it. Starting was understadable but in middle i din’t get the point any more.