VBSP generates wrong collision for some brushes

Author: L0jk4Created Apr 27, 2026Updated Sep 6, 2026

https://github.com/user-attachments/assets/f1d71779-8400-446a-bdbf-93a9e2a9738f

trikz_kyoto_fix setpos 13485.354492 -10322.815430 -12656.668945

Explanation

The issue lies with https://github.com/ValveSoftware/source-sdk-2013/blob/3300848d8a25ef6403c91f82a4cd97d6daefbc06/src/utils/vbsp/map.cpp#L471 Once an edge bevel plane is calculated, it is checked for correctness. https://github.com/ValveSoftware/source-sdk-2013/blob/3300848d8a25ef6403c91f82a4cd97d6daefbc06/src/utils/vbsp/map.cpp#L564-L606 Afterwards CMapFile::FindFloatPlane is used to insert it into the map (line 601), but the function only does so after trying to SnapPlane to an axial one. https://github.com/ValveSoftware/source-sdk-2013/blob/3300848d8a25ef6403c91f82a4cd97d6daefbc06/src/utils/vbsp/map.cpp#L336-L349

Aside from invalidating the earlier checks, this rounding will make the bevel plane's normal identical to one of the six mandatory axial brush sides added/verified earlier in CMapFile::AddBrushBevels. But convex brushes simply can't have two sides with the same normal, so the result is an incorrect collision against AABB (the only thing that uses bevel planes). Such bevels are generated for edges that nearly coincide with an axial plane. For me, this occurs when copy-pasting or moving a brush: a vertex originally aligned to the unit grid gets shifted slightly.

Fix

Removing the rounding will do the job, but for edges less than a hundred units long, such bevels aren't really noticeable. So you might want to ignore them entirely if the edge is short, as this would also help stay under the maximum plane count.

To fix collision on already compiled maps, one could create a plugin that, after a level change, iterates through the map's brushes and removes every axial brush side beyond the first six.

Update: wrote my own fix https://github.com/L0jk4/AxialBevelRemover

Extra

Map from the clip decompiled with bevels taken into account to reflect AABB collision: Image

An exaggerated illustration of what's going on: Image

A visualization with accurate calculations: https://www.desmos.com/calculator/dtupjyjppy

Another little bug

https://github.com/user-attachments/assets/6a2d8be1-ca89-440a-8528-7b79fb2ac93e

If an edge's direction is close enough to one of the axes, then it doesn't get any bevels. Therefore, brushes with such edges suffer a loss in collision accuracy: https://github.com/ValveSoftware/source-sdk-2013/blob/3300848d8a25ef6403c91f82a4cd97d6daefbc06/src/utils/vbsp/map.cpp#L546-557

Thanks to Maru for helping me compile vbsp and tweaking bspsrc.

Source: ValveSoftware/source-sdk-2013