star-2d

Contour structuring for efficient 2D geometric queries
git clone git://git.meso-star.fr/star-2d.git
Log | Files | Refs | README | LICENSE

commit dbb4560ff2d55e1818c44429864e38ab7c560857
parent 1f5ff47323c8e9f572d9b1e9323f5e1865b4ad0e
Author: Vincent Forest <vincent.forest@meso-star.com>
Date:   Tue, 22 Jun 2021 11:14:04 +0200

Update the API of the hit filter function

Add the submitted range as input argument. During ray-tracing, it is
simply the ray range. For closest-point queries, the range goes from 0
to the query radius.

Diffstat:
Msrc/s2d.h | 1+
Msrc/s2d_scene_view.c | 8+++++++-
Msrc/s2d_scene_view_closest_point.c | 12++++++++++--
Msrc/test_s2d_closest_point.c | 7++++++-
Msrc/test_s2d_scene_view2.c | 23++++++++++++++++++++---
Msrc/test_s2d_shape.c | 7++++---
Msrc/test_s2d_trace_ray.c | 32++++++++++++++++++++++++++++----
7 files changed, 76 insertions(+), 14 deletions(-)

diff --git a/src/s2d.h b/src/s2d.h @@ -157,6 +157,7 @@ typedef int (const struct s2d_hit* hit, const float ray_org[2], const float ray_dir[], + const float ray_range[2], void* ray_data, /* User data submitted on trace ray(s) invocation */ void* filter_data); /* Data defined on the setup of the filter function */ diff --git a/src/s2d_scene_view.c b/src/s2d_scene_view.c @@ -48,6 +48,7 @@ struct intersect_context { void* data; /* User defined data */ float ws_org[2]; /* World space ray origin */ float ws_dir[3]; /* World space ray direction */ + float ws_range[2]; /* World space ray range */ float cos_dir_dir2d; /* Cosine between the 3D ws_dir and its 2D projection */ int rt_3d; /* Define if the ray is traced in 3D */ }; @@ -808,6 +809,8 @@ scene_view_trace_ray intersect_ctx.ws_dir[0] = dir[0]; intersect_ctx.ws_dir[1] = dir[1]; intersect_ctx.ws_dir[2] = rt_3d ? dir[3] : 0.f; + intersect_ctx.ws_range[0] = range[0]; + intersect_ctx.ws_range[1] = range[1]; intersect_ctx.scnview = scnview; intersect_ctx.data = ray_data; intersect_ctx.rt_3d = rt_3d; @@ -1255,6 +1258,7 @@ rtc_hit_filter_wrapper(const struct RTCFilterFunctionNArguments* args) struct intersect_context* ctx; struct geometry* geom; struct hit_filter* filter; + int is_hit_filtered = 0; ASSERT(args && args->N == 1 && args->context && args->valid[0] != 0); rtc_rayN_get_ray(args->ray, args->N, 0, &ray_hit.ray); @@ -1270,7 +1274,9 @@ rtc_hit_filter_wrapper(const struct RTCFilterFunctionNArguments* args) if(ctx->rt_3d) { hit.distance /= ctx->cos_dir_dir2d; } - if(filter->func(&hit, ctx->ws_org, ctx->ws_dir, ctx->data, filter->data)) { + is_hit_filtered = filter->func + (&hit, ctx->ws_org, ctx->ws_dir, ctx->ws_range, ctx->data, filter->data); + if(is_hit_filtered) { args->valid[0] = 0; } } diff --git a/src/s2d_scene_view_closest_point.c b/src/s2d_scene_view_closest_point.c @@ -38,6 +38,7 @@ struct point_query_context { struct RTCPointQueryContext rtc; struct s2d_scene_view* scnview; + float radius; /* Submitted radius */ void* data; /* Per point query defined data */ }; @@ -94,6 +95,7 @@ static bool closest_point_line_segments (struct RTCPointQueryFunctionArguments* args, struct geometry* geom, + const float radius, void* query_data) { struct s2d_hit hit = S2D_HIT_NULL; @@ -103,12 +105,14 @@ closest_point_line_segments float v0[2], v1[2]; /* Segment vertices */ float N[2]; /* Segment normal */ float query_pos[2]; /* Submitted position */ + float range[2]; float closest_point[2]; /* Computed closest point */ float vec[2]; /* Vector from query pos to the closest point */ float dst; /* Distance to the closest point */ float s; /* Parametric coordinate of the closest point */ ASSERT(args && geom); ASSERT(args->primID < line_segments_get_nsegments(geom->lines)); + ASSERT(radius >=0); /* Fetch the line segments indices */ ids = line_segments_get_ids(geom->lines) + args->primID*2/*#indices per segment*/; @@ -145,11 +149,14 @@ closest_point_line_segments hit.u = s; hit.distance = dst; + range[0] = 0; + range[1] = radius; + /* `vec' is the direction along which the closest point was found. Submit it * to the filter function as the direction of the computed hit. */ filter = &geom->lines->filter; if(filter->func - && filter->func(&hit, query_pos, vec, query_data, filter->data)) { + && filter->func(&hit, query_pos, vec, range, query_data, filter->data)) { return 0; /* This point is filtered. Discard it! */ } @@ -174,7 +181,7 @@ closest_point(struct RTCPointQueryFunctionArguments* args) ASSERT(args->context->instStackSize == 0); geom = scene_view_geometry_from_embree_id(ctx->scnview, args->geomID); - return closest_point_line_segments(args, geom, ctx->data); + return closest_point_line_segments(args, geom, ctx->radius, ctx->data); } /******************************************************************************* @@ -213,6 +220,7 @@ s2d_scene_view_closest_point /* Initialise the point query context */ rtcInitPointQueryContext(&query_ctx.rtc); query_ctx.scnview = scnview; + query_ctx.radius = radius; query_ctx.data = query_data; /* Here we go! */ diff --git a/src/test_s2d_closest_point.c b/src/test_s2d_closest_point.c @@ -199,6 +199,7 @@ check_closest_point ******************************************************************************/ struct square_filter_context { float query_pos[2]; + float query_radius; unsigned prim_to_filter; }; @@ -207,6 +208,7 @@ square_filter (const struct s2d_hit* hit, const float org[2], const float dir[2], + const float range[2], void* query_data, void* filter_data) { @@ -215,7 +217,7 @@ square_filter float pos[3]; float vec[3]; - CHK(hit && org && dir && !S2D_HIT_NONE(hit)); + CHK(hit && org && dir && range && S2D_HIT_NONE(hit)); CHK((intptr_t)filter_data == (intptr_t)0xDECAFBAD); CHK(f2_normalize(vec, dir) != 0); @@ -227,6 +229,8 @@ square_filter if(!query_data) return 0; CHK(f2_eq_eps(ctx->query_pos, org, POSITION_EPSILON)); + CHK(range[0] == 0); + CHK(range[1] == ctx->query_radius); return ctx->prim_to_filter == hit->prim.prim_id; } @@ -302,6 +306,7 @@ test_square(struct s2d_device* dev) pos[1] = mid[1] + (rand_canonic() * 2 - 1) * (upp[1] - low[1]); f2_set(filter_ctx.query_pos, pos); + filter_ctx.query_radius = (float)INF; CHK(s2d_scene_view_closest_point (view, pos, (float)INF, &filter_ctx, &hit) == RES_OK); diff --git a/src/test_s2d_scene_view2.c b/src/test_s2d_scene_view2.c @@ -36,6 +36,13 @@ #define NSAMPS 10000 +struct ray_data { + struct s2d_primitive prim; + float ray_org[2]; + float ray_dir[2]; + float ray_range[2]; +}; + static INLINE float* ran_semi_disk_cos_local(float samp[2]) { @@ -61,16 +68,21 @@ discard_self_hit (const struct s2d_hit* hit, const float org[2], const float dir[2], + const float range[2], void* ray_data, void* filter_data) { - struct s2d_primitive* prim_from = ray_data; + struct ray_data* data = ray_data; CHK(hit != NULL); CHK(org != NULL); CHK(dir != NULL); + CHK(range != NULL); CHK((intptr_t)filter_data == (intptr_t)0xDECAFBAD); if(!ray_data) return 0; - return S2D_PRIMITIVE_EQ(prim_from, &hit->prim); + CHK(f2_eq(data->ray_org, org)); + CHK(f2_eq(data->ray_dir, dir)); + CHK(f2_eq(data->ray_range, range)); + return S2D_PRIMITIVE_EQ(&data->prim, &hit->prim); } static struct s2d_shape* @@ -132,6 +144,7 @@ int main(int argc, char** argv) { struct mem_allocator allocator; + struct ray_data ray_data; struct s2d_device* dev; struct s2d_scene* scn; struct s2d_scene_view* scnview; @@ -267,7 +280,11 @@ main(int argc, char** argv) f2_normalize(tmp, f2(tmp, 1, 1)); ran_semi_disk_cos(N, tmp); - CHK(s2d_scene_view_trace_ray(scnview, P, tmp, range, &prim, &hit) == RES_OK); + f2_set(ray_data.ray_org, P); + f2_set(ray_data.ray_dir, tmp); + f2_set(ray_data.ray_range, range); + ray_data.prim = prim; + CHK(s2d_scene_view_trace_ray(scnview, P, tmp, range, &ray_data, &hit) == RES_OK); CHK(S2D_HIT_NONE(&hit) == 0); sum += hit.distance; diff --git a/src/test_s2d_shape.c b/src/test_s2d_shape.c @@ -34,12 +34,13 @@ static int filter_none (const struct s2d_hit* hit, - const float org[3], - const float dir[3], + const float org[2], + const float dir[], + const float range[2], void* ray_data, void* filter_data) { - (void)hit, (void)org, (void)dir, (void)ray_data, (void)filter_data; + (void)hit, (void)org, (void)dir, (void)range, (void)ray_data, (void)filter_data; return 0; } diff --git a/src/test_s2d_trace_ray.c b/src/test_s2d_trace_ray.c @@ -31,24 +31,39 @@ #include <rsys/float2.h> +struct ray_data { + struct s2d_primitive prim; + float ray_org[2]; + float ray_dir[2]; + float ray_range[2]; +}; + static int filter_hit (const struct s2d_hit* hit, const float org[2], const float dir[2], + const float range[2], void* ray_data, void* filter_data) { - (void)dir, (void)org; + struct ray_data* data = ray_data; CHK(hit != NULL); + CHK(org != NULL); + CHK(dir != NULL); + CHK(range != NULL); CHK((intptr_t)filter_data == 0xDEADBEEF); if(!ray_data) return 0; - return S2D_PRIMITIVE_EQ((struct s2d_primitive*)ray_data, &hit->prim); + CHK(f2_eq(data->ray_org, org)); + CHK(f2_eq(data->ray_dir, dir)); + CHK(f2_eq(data->ray_range, range)); + return S2D_PRIMITIVE_EQ(&data->prim, &hit->prim); } int main(int argc, char** argv) { + struct ray_data ray_data; struct s2d_device* dev; struct s2d_shape* shape; struct s2d_scene* scn; @@ -140,8 +155,13 @@ main(int argc, char** argv) CHK(S2D_HIT_NONE(&hit) == 1); range[1] = FLT_MAX; + f2(dir, 0.f, -1.f); - CHK(RT(scnview, org, dir, range, &prim, &hit) == RES_OK); + f2_set(ray_data.ray_org, org); + f2_set(ray_data.ray_dir, dir); + f2_set(ray_data.ray_range, range); + ray_data.prim = prim; + CHK(RT(scnview, org, dir, range, &ray_data, &hit) == RES_OK); CHK(S2D_HIT_NONE(&hit) == 1); f2(dir, -1.f, 0.f); @@ -170,7 +190,11 @@ main(int argc, char** argv) CHK(S2D_HIT_NONE(&hit) == 0); CHK(S2D_PRIMITIVE_EQ(&hit.prim, &prim2) == 1); - CHK(RT(scnview, org, dir, range, &prim2, &hit) == RES_OK); + f2_set(ray_data.ray_org, org); + f2_set(ray_data.ray_dir, dir); + f2_set(ray_data.ray_range, range); + ray_data.prim = prim2; + CHK(RT(scnview, org, dir, range, &ray_data, &hit) == RES_OK); CHK(S2D_HIT_NONE(&hit) == 0); CHK(S2D_PRIMITIVE_EQ(&hit.prim, &prim) == 1);