## Planetary Horizon Culling

August 17, 2011

I overwrote my old blog site. The only article worth saving was this one:

I have started a planet renderer based on a quadtree structure.I needed to find a good horizon culling technique and the best one I found was at CrappyCoding, although it lacks a robust method to handle mountains over the horizon that are actually visible. I reworked the algorithm to use bounding spheres.I create a bounding sphere for each quad, and a horizon culling bounding sphere (HCBS). The HCBS starts with Dave Carlile’s technique but instead of keeping track of the angle between the camera vector and radius vector I keep track of the length of the horizon line (h). I then use ray casting to determine the intersection with the larger radius that includes the maximum mountain height.When processing the planet terrain quads I can compare the HCBS with the terrain quad bounding sphere. If they don’t intersect then it is culled.

```// Determine Length of h (see diagram)
// Pythagoreans theorem
// a2 + b2 = c2 (basic theorem)
// h2 + r2 = c2 (h = horizon, r = radius, c = camera)
float r2 = r * r;
float c = Game1.cameraComp.Camera.Position.Length();
float c2 = c * c;
float h2 = c2-r2;
float h = (float)Math.Sqrt(h2);

// Horizon Vector Length
// Determine arbritary point on horizon
double angleCamera = Math.Asin(radius / Game1.cameraComp.Camera.Position.Length());
Vector3 horizonNormal = Vector3.Normalize(newVector3((float)Math.Cos(angleCamera), (float)Math.Sin(angleCamera), 0));
Vector3 horizonPosition = Game1.cameraComp.Camera.Position + horizonNormal * h;

// Pick a point along the horizon line (h) that is well outside of the planet
// and then cast the ray back along the horizon line to determine a point
// on the expanded planetary bounding sphere. The expanded sphere includes the
// highest point (mountain).
Ray horizonRay = newRay(horizonPosition + horizonNormal * r, -horizonNormal);
BoundingSphere expandedPlanetSphere = newBoundingSphere(Vector3.Zero, r + highestPoint);float expandedDistance = horizonRay.Intersects(expandedPlanetSphere).Value;

// Make the bouding sphere (around camera) that represents any point within
// the expanded horizon
horizonSphere = newBoundingSphere(Game1.cameraComp.Camera.Position, h + expandedDistance);```