star-3d

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

commit 3e5fb1411c8d1b794b05e6685ff81d113a24d0ac
parent 7ec7b1b1676adaac344beaf22282a1ac930dee35
Author: Vincent Forest <vincent.forest@meso-star.com>
Date:   Tue, 22 Jun 2021 09:48:46 +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:
Mcmake/CMakeLists.txt | 2+-
Msrc/s3d.h | 1+
Msrc/s3d_scene_view_closest_point.c | 28+++++++++++++++++++++-------
Msrc/s3d_scene_view_trace_ray.c | 8+++++++-
Msrc/test_s3d_closest_point.c | 15+++++++++++++--
Msrc/test_s3d_scene_view.c | 3++-
Msrc/test_s3d_shape.c | 3++-
Msrc/test_s3d_sphere_instance.c | 3+++
Msrc/test_s3d_trace_ray.c | 24+++++++++++++++++++++---
Msrc/test_s3d_trace_ray_instance.c | 13++++++++-----
10 files changed, 79 insertions(+), 21 deletions(-)

diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright (C) 2015-2019 |Meso|Star> (contact@meso-star.com) +# Copyright (C) 2015-2020 |Meso|Star> (contact@meso-star.com) # # This software is a computer program whose purpose is to generate files used # to build the Star-3D library. diff --git a/src/s3d.h b/src/s3d.h @@ -214,6 +214,7 @@ typedef int (const struct s3d_hit* hit, const float org[3], const float dir[3], /* Direction from `org' to `hit' */ + const float range[2], /* Submitted range */ void* query_data, /* User data submitted on query invocation */ void* filter_data); /* Data defined on the setup of the filter function */ diff --git a/src/s3d_scene_view_closest_point.c b/src/s3d_scene_view_closest_point.c @@ -47,6 +47,7 @@ struct point_query_context { struct RTCPointQueryContext rtc; struct s3d_scene_view* scnview; + float radius; /* Submitted radius */ void* data; /* Per point query defined data */ }; @@ -167,6 +168,7 @@ closest_point_mesh (struct RTCPointQueryFunctionArguments* args, struct geometry* geom, struct geometry* inst, /* Can be NULL */ + const float radius, void* query_data) { struct s3d_hit hit = S3D_HIT_NULL; @@ -181,9 +183,9 @@ closest_point_mesh double vec[3]; double uv[2]; float dst; - float pos[3], dir[3]; + float pos[3], dir[3], range[2]; int flip_surface = 0; - ASSERT(args && geom && geom->type == GEOM_MESH); + ASSERT(args && geom && geom->type == GEOM_MESH && radius >= 0); ASSERT(args->primID < mesh_get_ntris(geom->data.mesh)); /* Fetch triangle indices */ @@ -267,14 +269,18 @@ closest_point_mesh + geom->scene_prim_id_offset + (inst ? inst->scene_prim_id_offset : 0); + range[0] = 0; + range[1] = radius; + /* `dir' is the direction along which the closest point was found. We thus * submit it to the filter function as the direction corresponding to the * computed hit */ f3_set_d3(dir, vec); f3_set_d3(pos, query_pos_ws); + filter = &geom->data.mesh->filter; if(filter->func - && filter->func(&hit, pos, dir, query_data, filter->data)) { + && filter->func(&hit, pos, dir, range, query_data, filter->data)) { return 0; /* This point is filtered. Discard it! */ } @@ -293,6 +299,7 @@ closest_point_sphere (struct RTCPointQueryFunctionArguments* args, struct geometry* geom, struct geometry* inst, + const float radius, /* User defined radius */ void* query_data) { struct s3d_hit hit = S3D_HIT_NULL; @@ -301,12 +308,13 @@ closest_point_sphere float query_pos[3]; float sphere_pos[3]; float Ng[3]; - float dir[3]; + float dir[3], range[2]; float uv[2]; float dst; float len; int flip_surface = 0; ASSERT(args && geom && geom->type == GEOM_SPHERE && args->primID == 0); + ASSERT(radius >= 0); /* Local copy of the query position */ query_pos[0] = args->query->x; @@ -377,12 +385,15 @@ closest_point_sphere + geom->scene_prim_id_offset + (inst ? inst->scene_prim_id_offset : 0); + range[0] = 0; + range[1] = radius; + /* Use the reversed geometric normal as the hit direction since it is along * this vector that the closest point was effectively computed */ f3_minus(dir, Ng); filter = &geom->data.sphere->filter; if(filter->func - && filter->func(&hit, query_pos, dir, query_data, filter->data)) { + && filter->func(&hit, query_pos, dir, range, query_data, filter->data)) { return 0; } @@ -419,10 +430,12 @@ closest_point(struct RTCPointQueryFunctionArguments* args) switch(geom->type) { case GEOM_MESH: - query_radius_is_upd = closest_point_mesh(args, geom, inst, ctx->data); + query_radius_is_upd = closest_point_mesh + (args, geom, inst, ctx->radius, ctx->data); break; case GEOM_SPHERE: - query_radius_is_upd = closest_point_sphere(args, geom, inst, ctx->data); + query_radius_is_upd = closest_point_sphere + (args, geom, inst, ctx->radius, ctx->data); break; default: FATAL("Unreachable code\n"); break; } @@ -464,6 +477,7 @@ s3d_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/s3d_scene_view_trace_ray.c b/src/s3d_scene_view_trace_ray.c @@ -48,6 +48,7 @@ struct intersect_context { void* data; /* Per ray user defined data */ float ws_org[3]; /* World space ray origin */ float ws_dir[3]; /* World space ray direction */ + float ws_range[3]; /* World space ray range */ }; /******************************************************************************* @@ -216,6 +217,8 @@ s3d_scene_view_trace_ray intersect_ctx.ws_dir[0] = dir[0]; intersect_ctx.ws_dir[1] = dir[1]; intersect_ctx.ws_dir[2] = dir[2]; + intersect_ctx.ws_range[0] = range[0]; + intersect_ctx.ws_range[1] = range[1]; intersect_ctx.scnview = scnview; intersect_ctx.data = ray_data; @@ -276,6 +279,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); @@ -296,7 +300,9 @@ rtc_hit_filter_wrapper(const struct RTCFilterFunctionNArguments* args) ASSERT(filter->func); hit_setup(ctx->scnview, &ray_hit, &hit); - 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/test_s3d_closest_point.c b/src/test_s3d_closest_point.c @@ -473,6 +473,7 @@ test_cbox_sphere(struct s3d_device* dev) ******************************************************************************/ struct sphere_filter_data { float query_pos[3]; + float query_radius; }; static int @@ -480,6 +481,7 @@ sphere_filter (const struct s3d_hit* hit, const float org[3], const float dir[3], + const float range[2], void* query_data, void* filter_data) { @@ -488,7 +490,7 @@ sphere_filter float pos[3]; float vec[3]; - CHK(hit && org && dir && !S3D_HIT_NONE(hit)); + CHK(hit && org && dir && range && !S3D_HIT_NONE(hit)); CHK((intptr_t)filter_data == (intptr_t)0xDECAFBAD); CHK(f3_normalize(vec, dir) != 0); @@ -498,6 +500,8 @@ sphere_filter CHK(f3_eq_eps(attr.value, pos, POSITION_EPSILON)); CHK(f3_eq_eps(data->query_pos, org, POSITION_EPSILON)); + CHK(range[0] == 0); + CHK(range[1] == data->query_radius); return 1; } @@ -588,6 +592,7 @@ test_sphere(struct s3d_device* dev) f3_splat(query_pos, 10); f3_set(filter_data.query_pos, query_pos); + filter_data.query_radius = (float)INF; CHK(s3d_scene_view_closest_point (scnview, query_pos, (float)INF, &filter_data, &hit) == RES_OK); CHK(!S3D_HIT_NONE(&hit)); @@ -615,6 +620,7 @@ enum cbox_geom { struct cbox_filter_data { float query_pos[3]; + float query_radius; unsigned geom_to_filter[3]; }; @@ -623,6 +629,7 @@ cbox_filter (const struct s3d_hit* hit, const float org[3], const float dir[3], + const float range[2], void* query_data, void* filter_data) { @@ -631,7 +638,7 @@ cbox_filter float pos[3]; float vec[3]; - CHK(hit && org && dir && !S3D_HIT_NONE(hit)); + CHK(hit && org && dir && range && !S3D_HIT_NONE(hit)); CHK((intptr_t)filter_data == (intptr_t)0xDECAFBAD); CHK(f3_normalize(vec, dir) != 0); @@ -643,6 +650,8 @@ cbox_filter if(!query_data) return 0; CHK(f3_eq_eps(data->query_pos, org, POSITION_EPSILON)); + CHK(range[0] == 0); + CHK(range[1] == data->query_radius); return data->geom_to_filter[0] == hit->prim.geom_id || data->geom_to_filter[1] == hit->prim.geom_id @@ -762,6 +771,7 @@ test_cbox(struct s3d_device* dev) pos[1] = (ucast.ui = 0x43e635b8, ucast.f); pos[2] = (ucast.ui = 0x4319ab78, ucast.f); f3_set(filter_data.query_pos, pos); + filter_data.query_radius = (float)INF; CHK(s3d_scene_view_closest_point (scnview, pos, (float)INF, &filter_data, &hit) == RES_OK); check_closest_point_cbox(pos, geom_id, &hit); @@ -795,6 +805,7 @@ test_cbox(struct s3d_device* dev) pos[2] = mid[2] + (rand_canonic() * 2 - 1) * (upp[2] - low[2]); f3_set(filter_data.query_pos, pos); + filter_data.query_radius = (float)INF; CHK(s3d_scene_view_closest_point (scnview, pos, (float)INF, &filter_data, &hit) == RES_OK); diff --git a/src/test_s3d_scene_view.c b/src/test_s3d_scene_view.c @@ -48,10 +48,11 @@ filter (const struct s3d_hit* hit, const float org[3], const float dir[3], + const float range[2], void* ray_data, void* filter_data) { - (void)org, (void)dir, (void)ray_data, (void)filter_data; + (void)org, (void)dir, (void)range, (void)ray_data, (void)filter_data; CHK(S3D_HIT_NONE(hit) == 0); return hit->prim.prim_id % 2 == 0; } diff --git a/src/test_s3d_shape.c b/src/test_s3d_shape.c @@ -42,10 +42,11 @@ filter_none (const struct s3d_hit* hit, const float org[3], const float dir[3], + 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_s3d_sphere_instance.c b/src/test_s3d_sphere_instance.c @@ -45,12 +45,15 @@ filter_front_face (const struct s3d_hit* hit, const float pos[3], const float dir[3], + const float range[2], void* ray_data, void* filter_data) { CHK(hit != NULL); CHK(pos != NULL); CHK(dir != NULL); + CHK(range != NULL); + CHK(range[0] < range[1]); CHK(filter_data == NULL); CHK(ray_data == NULL); CHK(S3D_HIT_NONE(hit) == 0); diff --git a/src/test_s3d_trace_ray.c b/src/test_s3d_trace_ray.c @@ -35,28 +35,41 @@ #include "test_s3d_cbox.h" #include "test_s3d_utils.h" -#include <rsys/image.h> +#include <rsys/float2.h> #include <rsys/float3.h> +#include <rsys/image.h> #include <string.h> #define IMG_WIDTH 640 #define IMG_HEIGHT 480 +struct ray_data { + float ray_org[3]; + float ray_dir[3]; + float ray_range[2]; +}; + static int filter_func (const struct s3d_hit* hit, const float pos[3], const float dir[3], + const float range[2], void* ray_data, void* filter_data) { + struct ray_data* data = ray_data; CHK(hit != NULL); CHK(pos != NULL); CHK(dir != NULL); - CHK((uintptr_t)ray_data == 0xDEADBEEF); + CHK(range != NULL); + CHK(ray_data != NULL); CHK((uintptr_t)filter_data == 0xDECAFBAD); CHK(S3D_HIT_NONE(hit) == 0); + CHK(f3_eq(pos, data->ray_org)); + CHK(f3_eq(dir, data->ray_dir)); + CHK(f2_eq(range, data->ray_range)); return hit->prim.prim_id % 2 == 0; } @@ -309,12 +322,17 @@ main(int argc, char** argv) pixel[1] = (float)iy/(float)IMG_HEIGHT; FOR_EACH(ix, 0, IMG_WIDTH) { + struct ray_data ray_data; const size_t ipix = (iy*IMG_WIDTH + ix) * 3/*RGB*/; pixel[0] = (float)ix/(float)IMG_WIDTH; camera_ray(&cam, pixel, org, dir); + + f3_set(ray_data.ray_org, org); + f3_set(ray_data.ray_dir, dir); + f2_set(ray_data.ray_range, range); CHK(s3d_scene_view_trace_ray - (scnview, org, dir, range, (void*)(uintptr_t)0xDEADBEEF, &hit) == RES_OK); + (scnview, org, dir, range, &ray_data, &hit) == RES_OK); if(S3D_HIT_NONE(&hit)) { ((uint8_t*)img.pixels)[ipix+0] = 0; diff --git a/src/test_s3d_trace_ray_instance.c b/src/test_s3d_trace_ray_instance.c @@ -56,11 +56,13 @@ struct ray { }; static int -filter(const struct s3d_hit* hit, - const float ray_org[3], - const float ray_dir[3], - void* ray_data, - void* filter_data) +filter + (const struct s3d_hit* hit, + const float ray_org[3], + const float ray_dir[3], + const float ray_range[2], + void* ray_data, + void* filter_data) { struct ray* ray = ray_data; @@ -68,6 +70,7 @@ filter(const struct s3d_hit* hit, CHK(ray_org != NULL); CHK(ray_dir != NULL); CHK(ray_data != NULL); + CHK(ray_range != NULL); CHK(filter_data == NULL); CHK(f3_eq(ray_org, ray->org) == 1); CHK(f3_eq(ray_dir, ray->dir) == 1);