Given the sphere's center and radius in world coordinates, and the current composite transformation matrix that includes both modeling and viewing transformations, we must project then center and perspectively scale the radius. Normally, a sphere would project to an ellipse and would require major and minor axis radii (not really, but it is a better approx than a circle; it is actually a "warped" ellipse), but in our approximation the sphere is projected into a circle and we need only find the "proper" scaling of the sphere radius to find a radius of the circle in pixel or screen space.
On PixelPlanes 4 and 5, the radius scaling factor used was the cube-root of the determinant of the 3x3 matrix formed from the transformed principle axes as follows:
The intuition for this scaling factor is based on the change in volume of a unit cube after transformation. We can define a unit cube with three orthonormal vectors. The volume of the parallelpiped formed from these vectors after transformation will be the scaling factor cubed. For a cube, the cube-root of the volume equals the length of a side. The approximation to the new "side length" is the cube-root of the volume of the cube after transformation. The ratio of the new side length to the old is the scaling factor that takes the world radius into screen radius (NDC coordinates).
The composite transformation matrix contains the transformed axes of this parallelpiped in the upper 3x3. The unit cube and its determinant is represented as follows:
-- X axis -- 0 -- Y axis -- 0 -- Z axis -- 0 0 0 0 1 1.000000 0.000000 0.000000 0.000000 0.000000 1.000000 0.000000 0.000000 0.000000 0.000000 1.000000 0.000000 0.000000 0.000000 0.000000 1.000000 Upper 3x3 Determinant = 1.000000 = volume of unit cube Side length = CubeRoot(1.000000) = 1If we scale the matrix so that the cube is a 2x2x2, we will see the reflected change in the determinant and the computed side length:
2.000000 0.000000 0.000000 0.000000 0.000000 2.000000 0.000000 0.000000 0.000000 0.000000 2.000000 0.000000 0.000000 0.000000 0.000000 1.000000 Upper 3x3 Determinant = 8.000000 = volume of tranformed cube Side length = CubeRoot(8.000000) = 2
The basic idea here is much simpler than the previous method. We simply take sample points on the boundary of the sphere and transform them along with the center. We can approximate the radius by the max distance between the center and the other boundary sample points. Sample points must be chosen so as to minimize the error from any viewing direction. As a minimum, we can choose three points chosen along the three principal axes emanating from the sphere's center.
As opposed to the previous method where we take sample points on the sphere in world coordinates irrespective of the viewer's position in hopes of finding samples near the projected boundary, we find samples on the silhouette in eye space. In eye space, we know that the eye is at the origin looking down the -Z axis (assuming OpenGL conventions). We can select sample points on the sphere boundary that are perpendicular to the viewing direction and then apply the remaining projection transformations to find the radius in NDC and/or screen space. We do have to have the radius in eye space, but this should be a simple calculation with the assumptions we make below.
This method has the potential to be the simplest of them all; however it requires some key assumptions. Basically, the composite matrix is formed from the multiplication of the Projection matrix with the ModelView matrix (ModelView being applied first, so Comp=Proj*Model for premult/col vectors). This method will be quite "accurate" if we can assume the following: