Planetary Horizon Culling

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.
Horizion Culling Diagram1

// Determine Length of h (see diagram)

// Pythagoreans theorem

// a2 + b2 = c2 (basic theorem)

// h2 + r2 = c2 (h = horizon, r = radius, c = camera)

float r = radius; 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(new Vector3((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 expande sphere includes the // highest point (mountain).

Ray horizonRay = new Ray(horizonPosition + horizonNormal * r, -horizonNormal);

BoundingSphere expandedPlanetSphere = new BoundingSphere(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 = new BoundingSphere(Game1.cameraComp.Camera.Position, h + expandedDistance);

Leave a Reply

You must be logged in to post a comment.