star-phor

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

commit adffac8b7f4ab05a33187a784bb8580e404975c7
parent 21cbf052694441408f10480ae68508cf0a2da64a
Author: Eduardo Fontana Lazzari <edufonlaz@gmail.com>
Date:   Fri,  1 Aug 2025 10:02:22 +0200

Create correspondence between primitives

This commit introduces the src2scn dynamic array as a member of the
source view structure. This array maps each prim_id from a source view
to the corresponding prim_id of the primitive in the global scene view
that shares the same vertex coordinates.

This correspondence is useful in several steps of path tracing. For
instance, it enables efficient self-hit checks between primitives from
different scene views. Previously, this required costly comparisons of
all vertex coordinates; now, it can be done by simply comparing the
prim_id of a source primitive to its counterpart in the global scene.

Diffstat:
Msrc/sphor_compute_mvrea.c | 8++++++++
Msrc/sphor_config.c | 58+++++++++-------------------------------------------------
Msrc/sphor_sources.c | 74+++++++++++++++++++++++++++++++++++---------------------------------------
Msrc/sphor_sources.h | 19+++++++++++--------
4 files changed, 63 insertions(+), 96 deletions(-)

diff --git a/src/sphor_compute_mvrea.c b/src/sphor_compute_mvrea.c @@ -62,6 +62,7 @@ compute_MVREA_realization float st[2] = {0}; /* Parametric coordinates of a point in a s3d_primitive */ int i = 0; /* Iterator */ size_t triangle_id; + size_t scn_prim_id; struct interface interface = INTERFACE_NULL; struct s3d_attrib attrib; struct s3d_hit hit = S3D_HIT_NULL; @@ -80,6 +81,13 @@ compute_MVREA_realization /* Sample a random position from a source in the whole scene */ res = sample_source_position(sphor, rng, &source_view, &prim, st); if (RES_OK != res){ goto error; } + + scn_prim_id = darray_size_t_data_get(&source_view->src2scn)[prim.prim_id]; + + res = s3d_scene_view_get_primitive + (sphor->scene_view, (unsigned)scn_prim_id, &prim); + if (RES_OK != res){ goto error; } + res = s3d_primitive_get_attrib (&prim, S3D_POSITION, st, &attrib); if (RES_OK != res){ goto error; } d3_set_f3(pos, attrib.value); diff --git a/src/sphor_config.c b/src/sphor_config.c @@ -512,48 +512,6 @@ 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 @@ -572,7 +530,9 @@ hit_filter_function struct s3d_primitive* prim = primitive; - return are_primitives_coordinates_identical(prim, &hit->prim); + if(hit->prim.prim_id == prim->prim_id) { return 1; } + + return 0; } /******************************************************************************* @@ -597,9 +557,13 @@ setup_config res = load_config(sphor, args); if (RES_OK != res) { goto error; } + /* Attach physical properties to primitives */ + res = setup_interfaces(sphor, suniq); + if (RES_OK != res) { goto error; } + /* Setup the scene views for each source to accelerate the sampling of a * position in a given source */ - res = setup_source_views(sphor, args); + res = setup_source_views(sphor, args, suniq); if (RES_OK != res) { goto error; } /* Compute distribution used to important sample a source with respect to @@ -607,13 +571,9 @@ setup_config res = setup_source_distrib_power(sphor, args); if (RES_OK != res) { goto error; } - /* Attach physical properties to primitives */ - res = setup_interfaces(sphor, suniq); - if (RES_OK != res) { goto error; } - /* Build accelerating structure for geometrical data */ res = setup_geometry_accel_struct - (sphor, suniq, S3D_TRACE, &sphor->scene_view); + (sphor, suniq, (S3D_TRACE | S3D_GET_PRIMITIVE), &sphor->scene_view); if (RES_OK != res) { goto error; } exit: diff --git a/src/sphor_sources.c b/src/sphor_sources.c @@ -38,10 +38,14 @@ register_surface_geometry (struct sphor* sphor, const struct sphor_create_args* args, const struct sphin_geometry* geom, - struct suniq* suniq) + struct suniq* suniq_scene, + struct suniq* suniq, + struct source_view* source) { struct sphin_geometry_descriptor geom_desc = SPHIN_GEOMETRY_DESCRIPTOR_NULL; size_t itri = 0; + size_t id_scene; + size_t id_source; res_T res = RES_OK; ASSERT(NULL != sphor); @@ -59,31 +63,15 @@ register_surface_geometry /* Reverse triangle normal if side is back: * - * In direct algorithms, the depart position of each path is sampled over - * the sources using a custom scene_view of each source. The custom scene - * view is different of the one composed by all triangles in the scene that - * is used in the rest of the path sampling. - * - * It means that, even though the sampled primitive of the source scene_view - * certainly has a corresponding primitive in the global scene_view, - * currently, there is no way of associating the sampled primitive in the - * source scene_view to the one in the global scene_view. Futhermore, the - * association s3d_primitive <-> sphor_interface does not exist for the - * source scene_views. Thus, it is not possible to correlate the - * geometrical data to the physical data as we do with the global - * scene_view. - * - * One of the consequences is that its not possible to retrieve the side - * (front or back) of the sampled primitive in the source_view that - * corresponds to the source. To overcome this issue, since a geometry can - * only be declared with one side at a time in sphin for the same source, - * the strategy taken is to store the triangle in the scene view in such a - * way that its normal points always to the hemisphere corresponding to the - * emitting side. In such a way, during path sampling, one can simply - * retrieve the normal of the sampled primitive and it will correspond to - * the emitting direction (subject to the convention: left or right-hand of - * each library) + * Since a geometry can only be declared with one side at a time in sphin + * for the same source, the strategy taken is to store the triangle in the + * scene view in such a way that its normal points always to the hemisphere + * corresponding to the emitting side. In such a way, during path sampling, + * one can simply retrieve the normal of the sampled primitive and it will + * correspond to the emitting direction (subject to the convention: left or + * right-hand of each library) */ + if (SPHIN_SIDE_BACK == geom_desc.side) { double tmp[3] = {0}; d3_set(tmp, tri.vertices[0]); @@ -91,8 +79,18 @@ register_surface_geometry d3_set(tri.vertices[1], tmp); } - res = suniq_register_triangle(suniq, &tri, NULL); + res = suniq_register_triangle(suniq, &tri, &id_source); if (RES_OK != res) { goto error; } + + /* Retrieve the id to the corresponding primitive in the scene */ + res = suniq_register_triangle(suniq_scene, &tri, &id_scene); + if (RES_OK != res) { goto error; } + + /* Append scene prim_id to the source <-> scene correspondance array */ + if (id_source == darray_size_t_size_get(&source->src2scn)){ + res = darray_size_t_push_back(&source->src2scn, &id_scene); + if (RES_OK != res) { goto error; } + } } exit: @@ -106,11 +104,11 @@ setup_source_view (struct sphor* sphor, const struct sphor_create_args* args, struct sphin_surface* surface, - struct s3d_scene_view** out_view) + struct suniq* suniq_scene, + struct source_view* source) { struct suniq* suniq = NULL; struct sphin_geometry* geom = NULL; - struct s3d_scene_view* view = NULL; size_t i_geometry = 0; size_t geometry_count = 0; res_T res = RES_OK; @@ -127,22 +125,17 @@ setup_source_view res = sphin_surface_get_geometry(surface, i_geometry, &geom); if (RES_OK != res) { goto error; } - res = register_surface_geometry(sphor, args, geom, suniq); + res = register_surface_geometry(sphor, args, geom, suniq_scene, suniq, source); if (RES_OK != res) { goto error; } } - res = setup_geometry_accel_struct(sphor, suniq, S3D_SAMPLE, &view); + res = setup_geometry_accel_struct(sphor, suniq, S3D_SAMPLE, &source->view); if (RES_OK != res) { goto error; } exit: if (NULL != suniq) { SUNIQ(ref_put(suniq)); } - *out_view = view; return res; error: - if (NULL != view) { - S3D(scene_view_ref_get(view)); - view = NULL; - } goto exit; } @@ -150,7 +143,8 @@ static res_T register_source_view (struct sphor* sphor, const struct sphor_create_args* args, - const size_t isurface) + const size_t isurface, + struct suniq* suniq_scene) { struct sphin_surface* surface = NULL; struct sphin_source_surface* source_surface = NULL; @@ -172,7 +166,7 @@ register_source_view source.sphin_id = isurface; - res = setup_source_view(sphor, args, surface, &source.view); + res = setup_source_view(sphor, args, surface, suniq_scene, &source); if (RES_OK != res) { goto error; } res = darray_source_view_push_back(&sphor->source_views, &source); @@ -191,7 +185,9 @@ error: res_T setup_source_views (struct sphor* sphor, - const struct sphor_create_args* args) + const struct sphor_create_args* args, + struct suniq* suniq_scene) + { struct sphin_source_surface* source_surface = NULL; struct sphin_surface* surface = NULL; @@ -213,7 +209,7 @@ setup_source_views if (RES_OK != res) { goto error; } if (NULL != source_surface) { - res = register_source_view(sphor, args, i_surface); + res = register_source_view(sphor, args, i_surface, suniq_scene); if (RES_OK != res) { goto error; } } } diff --git a/src/sphor_sources.h b/src/sphor_sources.h @@ -26,19 +26,23 @@ #include <star/s3d.h> #include <rsys/dynamic_array.h> +#include <rsys/dynamic_array_size_t.h> /* Forward declarations */ struct sphor; struct sphor_create_args; +struct suniq; struct s3d_scene_view; struct ssp_rng; struct source_view { struct s3d_scene_view* view; /* View of the source */ + struct darray_size_t src2scn; /* Map the prim id of a source to its prim in + the scene */ size_t sphin_id; /* Surface identifier in star-phor-input */ }; -#define SOURCE_VIEW_NULL__ {NULL, 0} +#define SOURCE_VIEW_NULL__ {0} static const struct source_view SOURCE_VIEW_NULL = SOURCE_VIEW_NULL__; static INLINE void @@ -49,9 +53,8 @@ source_init ASSERT(NULL != allocator); ASSERT(NULL != source); - (void) allocator; - *source = SOURCE_VIEW_NULL; + darray_size_t_init(allocator, &source->src2scn); } static INLINE void @@ -64,6 +67,7 @@ source_release S3D(scene_view_ref_put(source->view)); source->view = NULL; } + darray_size_t_release(&source->src2scn); } static INLINE res_T @@ -77,8 +81,7 @@ source_copy dst->sphin_id = src->sphin_id; S3D(scene_view_ref_get(src->view)); dst->view = src->view; - - return RES_OK; + return darray_size_t_copy(&dst->src2scn, &src->src2scn); } static INLINE res_T @@ -93,8 +96,7 @@ source_copy_and_release dst->view = src->view; src->view = NULL; - - return RES_OK; + return darray_size_t_copy_and_release(&dst->src2scn, &src->src2scn); } /* Generate darray_source_view data type and API */ @@ -109,7 +111,8 @@ source_copy_and_release extern LOCAL_SYM res_T setup_source_views (struct sphor* sphor, - const struct sphor_create_args* args); + const struct sphor_create_args* args, + struct suniq* suniq_scene); extern LOCAL_SYM res_T setup_source_distrib_power