I've been thinking for a while that I need to go back to my XNA BSP Processor / Importer to optimize the output a little more and my current focus is optimizing the patch meshes in the BSP. We use NetRadiant to create our game levels in BSP format (and for our track builder I export each piece as an individual BSP then convert it into a mesh since I'm not really a modeller but I'm pretty good with level editing tools).
The first screenshot here shows how the current engine tesselates all patch meshes with a fixed LOD at compile time (with a tesselation factor of 9). This means that every patch mesh in the BSP generates 100 new vertices and takes 162 triangles to render the mesh. Now the problem is that some of these meshes do not need to be tesselated so much and can infact be rendered with many less polygons.
The second screenshot shows the optimal tesselation of the main road patch mesh. You can see that the exact same patch mesh can be rendered using only 18 triangles rather than 162! To do this I either need to try and add some fancy code into the tesselation function that can split the patches depending on the curvature of each side or I can try to supply variables with each patch surface that specify the tesselation to be used.
I've decided that the latter method is the easiest and I can add surfaceflags for each patch surface in the BSP which will specify the tesselation to be used on X and Y edges. For the corner piece in the previous screenshots I would specify an X of 9 and Y of 1 so the patch would not be split vertically and the tesselation would create the 18 triangle version of the patch.
These screenshots show the most extreme example of the problem. A flat piece of road is made with a single patch mesh which would automatically be tesselated 9x9 times resulting in 100 vertices and 162 triangles again. This could be reduced down to only 2 triangles and 4 vertices if we basically do no tesselation with factors of 1 for both X and Y.
Even the curved pieces along the edge of the road only need to be tesselated once in the X direction for a flat piece of road (but still need to tesselate 9 or so times in the Y since they are curved). For that single section of road (and every other section in our track builder) there are 12 patch meshes. Using the current tesselation function this would result in 100 vertices and 162 triangles per mesh, resulting in 1200 vertices and 1944 triangles. (I hadn't quite realised until now just how high that count was!).
For the straight pieces of road we can reduce the tesselation along the X axis to 1 for all patches. This instantly reduces our polygons per patch to 18 and the section of track would then contain 240 vertices and 216 triangles.
Four of the patches are flat and hence only require tesselation once in both the X and Y directions so that brings our triangle count down even further. Some of the patches are also rather small compared to others and the curves do not need to be as smooth as others. After taking all optimizations into account we end up with the following tesselations:
Road surface: 1 x 1 : 4 vertices, 2 triangles
Road underside: 1 x 1 : 4 vertices, 2 triangles
Road edge (left): 1 x 5 : 12 vertices, 10 triangles
Side Light (left): 1 x 1 : 4 vertices, 2 triangles
Side barrier (left) : 1 x 7 : 16 vertices, 14 triangles
Side barrier top (left) : 1 x 3 : 8 vertices, 6 triangles
Outer edge (left) : 1 x 7 : 16 vertices, 14 triangles
Road edge (right): 1 x 5 : 12 vertices, 10 triangles
Side Light (right): 1 x 1 : 4 vertices, 2 triangles
Side barrier (right) : 1 x 7 : 16 vertices, 14 triangles
Side barrier top (right) : 1 x 3 : 8 vertices, 6 triangles
Outer edge (right) : 1 x 7 : 16 vertices, 14 triangles
Our newly optimized section of road has now been reduced from 1200 vertices and 1944 triangles down to 120 vertices and 96 triangles!
I'm going to be working on making these changes to our BSP loader over the next day or two and hope to see from huge gains in performance terms from this track builder game so that the players are able to build much larger and more complex tracks.
If you found this post helpful please leave a comment below: