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.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
// 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(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);