star-phor

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

commit aba7e50b586998d548fa314d6b90188361a22f4f
parent 430ae867b63ad4aaaf3535edd76d6e6359fb4992
Author: Eduardo Fontana Lazzari <edufonlaz@gmail.com>
Date:   Wed,  9 Jul 2025 14:20:09 +0200

Attach a hit filter function to the global scene view

During path sampling, the hit function is responsible for discarding
ray-geometry intersections that should not be considered valid.

Currently, only self-intersections are discarded. A hit is considered
a self-intersection when the primitive from which the ray originates
is the same as the one it intersects. Self-intersections are usually
detected by comparing the IDs of the primitives, assuming they belong
to the same scene_view.

However, in star-phor, there are multiple scene_views: one containing
all primitives, and one scene_view per source used in sampling.
Therefore, ID comparison is not sufficient. Instead, self-intersections
are detected by comparing the coordinates of the three vertices of the
departing and intersected primitives, which allows filtering out
self-intersections even across different scene_view contexts.

Diffstat:
Msrc/sphor_config.c | 67+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 67 insertions(+), 0 deletions(-)

diff --git a/src/sphor_config.c b/src/sphor_config.c @@ -25,6 +25,7 @@ #include "sphor.h" #include "sphor_c.h" +#include <rsys/float3.h> #include <star/sphin.h> #include <star/s3d.h> #include <star/suniq.h> @@ -511,6 +512,69 @@ error: goto exit; } +/* Check if two primitives are geometrically identical by comparing the coordinates + * of their vertices. If all vertices have the same positions, return 1; otherwise, + * return 0. This function is particularly useful when dealing with configurations + * composed of multiple scenes, where primitive IDs may not be reliable. + * In cases where primitives are known to belong to the same scene, it is simpler + * and more efficient to compare their IDs directly. */ +static int +are_primitives_coordinates_identical( + const struct s3d_primitive* prim0, + const struct s3d_primitive* prim1) +{ + struct s3d_attrib prim0_pos; + struct s3d_attrib prim1_pos; + int i, j; /* Iterators */ + /* Barycentric coordinates corresponding to each one of the vertices in the + * primitive */ + float st[3][2] = {{0,0}, {0,1}, {1,0}}; + + ASSERT(NULL != prim0); + ASSERT(NULL != prim1); + + FOR_EACH(i, 0, 3) { + int equal = 0; + s3d_primitive_get_attrib(prim0, S3D_POSITION, st[i], &prim0_pos); + FOR_EACH(j, 0, 3) { + s3d_primitive_get_attrib(prim1, S3D_POSITION, st[j], &prim1_pos); + if (1 == f3_eq(prim0_pos.value, prim1_pos.value)) { + equal = 1; + break; + } + } + if (1 != equal) { + /* vertex i of prim0 does not match any vertex in prim1 -> primitives + * vertices are not the same */ + return 0; + } + } + /* All vertices in prim0 match exactly one vertex in prim1 -> primitives are + * the same */ + return 1; +} + +/* Function attached to the scene view that determines whether a hit is valid. + * Returns 0 if the hit is valid, 1 otherwise. */ +static int +hit_filter_function + (const struct s3d_hit* hit, + const float pos[3], + const float dir[3], + const float range[2], + void* primitive, + void* interface) +{ + (void)pos; + (void)dir; + (void)range; + (void)interface; + + struct s3d_primitive* prim = primitive; + + return are_primitives_coordinates_identical(prim, &hit->prim); +} + /******************************************************************************* * Local functions ******************************************************************************/ @@ -652,6 +716,9 @@ setup_geometry_accel_struct res = s3d_scene_create(device, &scene); if (RES_OK != res) { goto error; } + res = s3d_mesh_set_hit_filter_function(shape, hit_filter_function, NULL); + if (RES_OK != res) { goto error; } + res = s3d_scene_attach_shape(scene, shape); if (RES_OK != res) { goto error; }