pub fn screen_space_tess_factor(
desc: &CylinderDescriptor,
cam: &Camera,
viewport: (u32, u32),
target_px: f64,
) -> TessFactorExpand description
Derive a TessFactor from the cylinder’s projected screen size so the
silhouette’s chord error stays within target_px pixels at the given view.
A zoomed-in cylinder (large projected radius) gets a fine mesh; a distant one (small projected radius) gets a coarse mesh — view-dependent LOD, the payoff of meshing analytic surfaces on the GPU from their parameters.
§Math
The chord error of an n_u-gon inscribed in a circle of radius r is
ε = r·(1 − cos(π/n_u)). Projecting r to pixels under perspective,
r_px = r · (H/2) / (d · tan(fov_y/2)) where H is the viewport height and
d is the center’s view-space depth (its projection onto the view
direction, view_dir · (center − eye)) — not the Euclidean eye distance, so
an off-axis cylinder at the same depth is not under-tessellated. Bounding the
screen-space error r_px·(1 − cos(π/n_u)) ≤ target_px and solving:
n_u = ceil(π / acos(1 − clamp(target_px / r_px, 0, 2))). A sub-pixel
cylinder (r_px ≤ target_px) floors to the TessFactor minimum; a cylinder
engulfing the camera (r_px → ∞) requests the maximum.
n_v is fixed at 1: a cylinder’s lateral face is ruled (straight and of
constant normal along the axis), so one axial division is geometrically and
shading-exact. Sphere/torus surfaces will later need n_v adaptivity too,
since they curve in both parametric directions.
The result always passes through TessFactor::new, so the
[3, MAX_TESS] clamp and the buffer-overflow guard still apply.