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:
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);