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
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
//! GIA/AGSL-style optical gemological metrics (brilliance, fire,
//! scintillation, windowing, extinction).
//!
//! Evaluated by firing an analytical ray fan through a stone's facet geometry from the
//! observer's point of view, under the lighting the renderer itself uses.
//!
//! # What is measured
//!
//! Each evaluation traces an 18x18 grid of rays (the cells inside a disc, see below), each
//! with a five-ray sub-aperture bundle, at the d-line. Every ray is classified once:
//!
//! - **Windowing**: the ray leaks out through the pavilion instead of returning.
//! - **Brilliance**: the ray leaves upward through the crown and is *visibly returned* --
//! outside the observer's 16 degree head-shadow cone and looking at a light source (see
//! the lighting model below).
//! - **Extinction**: every other ray -- trapped, absorbed, head-shadowed or looking at the
//! dim surround. The three percentages are shares of all the rays that hit the stone;
//! a ray blocked at entry counts in the total but in none of the three.
//! - **Fire**: for each returned ray, the angle between its F-line and C-line exit
//! directions, weighted by the product of the three wavelengths' Fresnel transmittances
//! and the two exit cosines, summed over the rays and divided by the total rays. Only
//! pairs that exit through the same facet after the same number of bounces count.
//! - **Scintillation**: the spatial contrast (coefficient of variation) of the per-cell
//! return fraction, squashed into 0-100, blended 60/40 with the temporal flicker of the
//! cells' return status as the camera yaws through +/-3 degrees.
//!
//! # Face-up tone
//!
//! [`evaluate_gem_optical_metrics_with_tone`] adds the colour of the light the stone returns
//! to the observer ([`FaceUpTone`]), from the same grid pass. The returned rays' Fresnel
//! weights are binned by internal path length (128 bins over 12 girdle half-widths), and the
//! transmittance is the Beer-Lambert *mixture* over those paths, not Beer-Lambert of the mean
//! path; the pose is meant to be table-up. The colorimetry runs under the lighting preset's
//! own spectrum and white point ([`ToneIlluminant`]): Lab is relative to that white, so a
//! colourless stone is neutral under every preset, and the sRGB swatch is adapted to the
//! screen's D65 the way the Live Render white-balances that preset. UV lamps and HDR maps
//! have no usable white point and fall back to D65. The stone's size enters only through
//! `GemMaterial::absorption_path_scale` in the exponent. A head-shadow setting (a separate
//! lighting plan may add one) enters only the Returned classification, never the tone's
//! colorimetry.
//!
//! # Lighting model
//!
//! The metrics take the same [`EnvironmentSource`](crate::optics::raytracer::EnvironmentSource)
//! the tracer renders with, so a preset or light change moves the numbers the way it moves
//! the picture. A ray counts as looking at
//! a light source when the environment's radiance along its exit direction exceeds a
//! multiple of the environment's ambient level (the median radiance over the upper
//! hemisphere): for the four studio presets that is the very key softbox, fill softbox and
//! ring pinpoint lobes the tracer evaluates, for the light tent its overhead softbox and
//! spark light, for the daylight dome its sun, for an HDR panorama its bright regions.
//! The ISO hemisphere is uniformly radiant, so every direction it radiates into counts.
//! The observer's head-shadow cone is applied on top, separately. The details and their
//! edge cases are on the private `lighting` module.
//!
//! # Facet finishes
//!
//! The tilt sweeps ([`evaluate_all_axes_profiles_finished_threaded`],
//! [`evaluate_full_axis_profile_at_azimuth_finished_threaded`] and the stepped variant) take a
//! [`FinishedStone`]: the planes and tools plus a per-facet finish list. A frosted facet scatters
//! the way the render tracer's frosted bounce does (a broadband Fresnel reflect/transmit split and
//! a cosine-weighted direction, see the private `frosted` module), so a frosted design's tilt
//! curves differ from its polished ones. An empty list, or one with no frosted facet, is the
//! polished stone and gives bit-identical results to the plain-geometry entry points, which is
//! also what every other metric uses: the live HUD numbers
//! ([`compute_or_reuse_metrics_geom`]), the optimiser's scoring and the Compare deltas take no
//! finishes and see every facet polished.
//!
//! # Fan scale
//!
//! The grid is scaled to the stone: the sampled disc reaches 95% of the measured girdle
//! half-width ([`render_setup::measure_model_width`] halved; 1.0 model unit when the
//! design does not measure), and the rays start two and a half half-widths from the
//! stone's centre. An elongated outline is covered along its short axis only. See the
//! private `fan` module.
//!
//! [`render_setup::measure_model_width`]: crate::render_setup::measure_model_width
//!
//! # Layout
//!
//! Split by responsibility: [`camera`] (the shared observer-PoV basis, read off the render
//! camera), [`fan`] (where the rays start), [`lighting`] (the illumination model),
//! [`types`] (the [`GemOpticalMetrics`] result and the 19-point elevation grid),
//! [`ray_trace`] (the single-wavelength refract-then-bounce physics core), [`visibility`]
//! (the head-shadow/illumination "is this ray visibly returned" test), [`scintillation`]
//! (the spatial+temporal sparkle terms), [`classify`] (per-aperture-sample ray
//! classification and the Fire bifurcation gate), [`evaluate`] (the main grid loop,
//! [`evaluate_gem_optical_metrics`]), [`profile`] (the angular-profile sweeps built on top
//! of it), [`sweep`] (the four-axis tilt sweep) and [`cache`] (reuse of the results while
//! their inputs, lighting included, do not change).
pub use ;
pub use evaluate_optical_image;
pub use ;
pub use *;
pub use ;
pub use camera_view_basis;
pub use ;
pub use FinishedStone;
pub use ;
pub use ;
pub use ;
pub use ;