Fix horizon culling causing terrain tiles to disappear#189
Fix horizon culling causing terrain tiles to disappear#189SamHL wants to merge 1 commit intopelicanmapping:mainfrom
Conversation
Visual symptoms: - At certain camera orientations, large portions of the visible Earth (often an entire hemisphere) would suddenly disappear - The issue was orientation-sensitive: a small rotation of the camera would cause the missing terrain to reappear - Most noticeable when viewing the globe from orbital distances Root cause: The horizon culling in SurfaceNode::isVisible() was calling Horizon::isVisible() with radius=0, treating each tile's horizon culling point as an infinitesimal point rather than accounting for the tile's actual spatial extent. This caused tiles near the horizon boundary to be incorrectly culled even when part of the tile should have been visible. Additionally, Horizon::isVisible() had a potential numerical precision issue where the calculation `sqrt(dot(VT,VT) - a*a)` could produce NaN if floating-point errors caused the value under the sqrt to go negative. The fix: 1. SurfaceNode.h: Pass the tile's bounding sphere radius to the horizon visibility test, making culling more conservative by accounting for the tile's actual size 2. Horizon.cpp: Add numerical safeguards to prevent NaN propagation: - Clamp cSquared to >= 0 before taking sqrt - If the final result is NaN, default to treating tile as visible
|
Hi Sam and thanks for the submission. I haven't seen this problem; do you have steps to reproduce it? I ask because the whole idea of the "horizon culling point" is to be a single point (without any radius) that can determine the visibility of the entire tile. Here's a reference article: It is definitely possible we are not calculating the point correctly and that is causing artifacts (though I have not seen this problem personally). |
|
For now I decided to add (a variation of) the Horizon checks. |
Root cause:
The horizon culling in SurfaceNode::isVisible() was calling Horizon::isVisible() with radius=0, treating each tile's horizon culling point as an infinitesimal point rather than accounting for the tile's actual spatial extent. This caused tiles near the horizon boundary to be incorrectly culled even when part of the tile should have been visible.
Additionally, Horizon::isVisible() had a potential numerical precision issue where the calculation
sqrt(dot(VT,VT) - a*a)could produce NaN if floating-point errors caused the value under the sqrt to go negative.The fix:
SurfaceNode.h: Pass the tile's bounding sphere radius to the horizon visibility test, making culling more conservative by accounting for the tile's actual size
Horizon.cpp: Add numerical safeguards to prevent NaN propagation: