star-phor

Radiative transfer solver for photoreactors.
git clone https://www.edstar.cnrs.fr/git/star-phor.git
Log | Files | Refs | README | LICENSE

commit 34cfdb97f8eb4e6ee8245ec04f67197cb29f4051
parent dc7eb4e681146cc588ae724c857f3ce6fb3fc964
Author: Eduardo Fontana Lazzari <edufonlaz@gmail.com>
Date:   Wed, 28 Jan 2026 17:42:51 +0100

Fix: ensure correct emission hemisphere by tracking surface side

The source direction sampling logic previously assumed scene geometry
normals were always oriented toward the emission direction. Since scene
normals are arbitrary, this resulted in incorrect emission hemispheres
for "back-facing" triangles.

Fix it by checking the scene normal against the source reference during
position sampling and conditionally inverting it during direction sampling.

Diffstat:
Msrc/sphor_ran_source.c | 23+++++++++++++++++++++--
1 file changed, 21 insertions(+), 2 deletions(-)

diff --git a/src/sphor_ran_source.c b/src/sphor_ran_source.c @@ -99,7 +99,17 @@ source_surface_sample_direction res = sphin_source_surface_get_direction_distribution(source, &src_dir_dist); if (RES_OK != res) { goto error; } - d3_set(normal, prim_pos->primitive.normal); + /* Determine the effective emission normal. + * Since scene geometry normals can be arbitrary, we use the pre-calculated + * 'side' property of the primitive obtained during positiob sampling to + * ensure the normal points into the emission hemisphere. */ + if (SPHIN_SIDE_FRONT == prim_pos->primitive.side) { + /* Normal aligns with emission. Use as us */ + d3_set(normal, prim_pos->primitive.normal); + } else if (SPHIN_SIDE_BACK == prim_pos->primitive.side) { + /* Normal oposed to emission. Invert it */ + d3_minus(normal, prim_pos->primitive.normal); + } else { res = RES_BAD_ARG; goto error; } switch (src_dir_dist.type) { case SPHIN_SOURCE_DIRECTION_COLLIM: @@ -189,7 +199,8 @@ sample_source_position f3_normalize(src_normal.value, src_normal.value); f3_normalize(scn_normal.value, scn_normal.value); - /* Flip the normal in Star-Phor convention, i.e., right-hand rule */ + /* S3D and star-phor use different conventions. + * Flip the normal in Star-Phor convention, i.e., right-hand rule */ f3_minus(src_normal.value, src_normal.value); f3_minus(scn_normal.value, scn_normal.value); @@ -202,6 +213,14 @@ sample_source_position position->primitive.normal[1] = scn_normal.value[1]; position->primitive.normal[2] = scn_normal.value[2]; + /* During setup, source geometry normals are explicitly oriented toward the + * emission direction. Scene geometry normals, however, are arbitrarily + * oriented based on initial triangle traversal. + * + * By calculating the dot product of these two normals, we determine if the + * scene's face orientation aligns with the emission direction, allowing us + * to label the emitting side */ + if (f3_dot(src_normal.value, scn_normal.value) > 0) { /* The scene normal points in the same direction of the source normal, that * points on the emission direction, i.e., */